Order for storing user id vs user group - php

I'm currently working on a custom add-on for a forum, where it checks a json file to see if a user has permission to moderate a certain group. I was wondering in what order I should store this information.
Let's say my demo information is: User 1 and 2 have access to edit Group A. User 1 also has access to edit Group B.
Order 1 - ID First, Then Group (Mockup)
{
"1": [
"A",
"B"
],
"2": [
"A"
]
}
Order 2 - Group First, Then Id (Mockup)
{
"A": [
"1",
"2"
],
"B": [
"1"
]
}
Which one is easier to manage/work with when you're using php? (Or are either of these wrong when storing data in json? Should I be using some other combo? I don't want to use MySQL for this, since it's going to be a really small set of users who can manage these groups)

Whenever I see a question like this, where there is not really a correct answer, as there are so many possibilities, I tend to think the OP is just trying to be as exhaustive and pedantic as possible in their research to find the best option, and that is really a great kind of curiosity, suited perfectly for programming. Knowing this, here are some thoughts.
Thoughts
I think you should look at this in a different way. When users can be differentiated by the privileges they are granted, you are essentially defining roles. Every role is distinguished by its level of access to content and how much that content can be modified.
When framing it like this, think of a pyramid. The most privileged roles have the best overview of all content, and consequently will be able to modify it according to their discretion. There are very few of these people. Descending the pyramid results in more and more people for every level of the pyramid, with an ever decreasing overview of the content and the ability to modify it. This continues until you reach the bottom of the pyramid, or the "Basic" user role, which the majority of the members of any community will be granted by default. They are the foundation of the pyramid but have very few privileges.
This means that users at the top of the community are granted more weight in their decisions. For example, say the highest role in a community is "Administrator." Any user granted this role can do anything. That is a lot of responsibility to carry. To put this in weighted terms, this role will be assigned a weight of 100. Beneath the Administrator are the "Moderators." They are essential to the community, but granting them the ability to delete entire categories and all child content might be too much power; they should be allowed to ban users and delete some content. If an Administrator fires them before demoting their role, they can totally destroy the community. Knowing this, Moderators do carry weight, but not as much as Administrators. They will be assigned a weight of 75. The community needs "Janitors" to clean up spam and reposts, but they should not be allowed to ban or delete users. Consequently, you assign them a weight of 50. This distribution of weight continues until all roles have been defined, each with distinct privileges.
The Question
Tying this together, sure, you can hardcode a specific user ID to a specific group ID, or vice versa, but that can become difficult to manage at some point, especially considering the duplication involved.
Consider then, that groups should only be accessed by users with a given weight. For example, Group A is assigned a user access weight of 25, and group B is assigned a user access weight of 10. What this means is that any users who have a weight of 25 or more will have automatic access to group A, and of course because group B only requires a user with a weight of 10, any user that can access group A can definitely access group B as well, because 25>10. In pyramid terms, 25 is equal to or greater than groups assigned a user access weight of 25 or 10. With this type of setup, there can be dozens of groups, each with their own user weight access. Further, that is the only variable that needs to be assigned to a group, instead of having to keep complicated user access lists for every group, or vice versa, with users keeping track of ever-growing lists of group IDs they can access.
With this knowledge, consider the example you provided. User 1 has access to edit group A and B. User 2 only has access to edit group B. This implies that User 1 has more privileges. If user 1 has more privileges, he also happens to carry more weight than user 2. Let us say that user 1 is assigned a weight of 30, while user 2 is assigned a weight of 15. Tying into the group scenario just described, this would mean that user 1 (weight: 30) can definitely access both groups A (weight user access: 25) and B (weight user access: 10), because 30 > 25 > 10. User 2, on the other hand, can only access group B, because 15 > 10. Furthermore, this means that while user 2 cannot access group A, it does not mean that he could not, for example, access group C, with a minimum user weight requirement of 5, because 15 > 10 > 5. In addition, this obviously means that user 1 could also access group C.
Afterword
You wake up one day and realize that group B should not be accessed by the community proletariat, with their peasant role weights of 10. Group B should be for the more dignified of the community, with weights of, like, 11 or more, so you increase the minimum role weight requirement of group B to 11. With a single change to a single integer assigned to group B, you have just prevented every single user with a weight of 10 or less from accessing their once cherished group B. The prole is not happy, but you do not care, because you are the community god, with a weight well over 9000, and you can do whatever the hell you want. You can also do it without having to modify dozens, hundreds, thousands, or millions of specific user/group access lists that are, as mentioned, way too clunky and unmanageable.
This is how smart access control is managed.

Related

Is this good implementation of action-based user levelling system?

For now, the system should have 6 different user levels.
Each level will be gained upon user activity, for example:
Level 1 - When user register
Level 2 - When user completes a mission
Level 3 - When user completes more than one mission
Level 4 - When user donate > $X amount of money
Level 5 - When user write more than 50 comments in blog
Level 6 - When user complete quiz
And now... I'm wondering, what's the best database schema to achieve this? I should keep track of all actions related to user's activities, that's why I though about xp_events table... Something like this:
id # primary key
event # type of event, e.g. 'register', 'complete_quiz', etc.
user_id # id of user
delta # number of "exp" which will be gained after specific action
And... in users table I will keep record of current level and "exp" which each user has earned until now.
When user makes any activity, I will call a trigger which will check if user have new level unlocked.
But... I'm aware that in long term (e.g. if more levels are added), this isn't optimal solution.
Looking forward for any suggestions.
I see two obvious possibilities here.
One is to have an event table like you say, with a user ID, event ID, dollar amount (for donations), probably a date/time, maybe other data. If the only reason why you are keeping any of this data is to determine each user's level, this is simple and effective.
If you're keeping track of this data for other purposes also, you probably want to separate it into multiple tables. In such a case you would likely have other data you need to keep for each event. Like for a donation you would need dollar amounts, which I assume don't apply to comments and missions. For comments you likely need the text of the comment and some indication of the thread this comment is on or what it's subject is. For a mission -- I don't know what a "mission" is in this context, but you likely want some information about the type of mission and where it was or who they were supposed to kill or whatever. Most of this data would not be applicable to events of different types. A comment probably doesn't have a dollar amount, a mission doesn't have a thread, etc. So you'd end up with a lot of irrelevant data and bunches of null fields.

Database Setup for Multilevel User Rights

I'm looking to create a database for users with multi-level user rights and I don't know how to go about doing this. What I mean is that I want a manager of a business to be able to purchase my product; that person would be given Owner rights, but would also be able to grand additional users under that license--those people would be given Manager or User rights. Each level (as well as my level: Admin, and my staff: SuperUser) would obviously have individual rights/privileges).
What I'm asking, more specifically, is how to set up the database. For example, if my business is a corporate calendar/organizer, the Owner would set up departments, each with a Manager and many Users. What's the best and most efficient way to structure the database? Like, would each user (and each calendar entry) have to be associated with an ID that belongs to that specific Owner account? I'm just a little lost as to what the best way to organize the database to keep everything together, as I will have multiple different Owners with their own company structure under them.
I want to use MySQL and PHP.
I tried to make this as logical as possible. I think I'm making it too hard, but I am sure there is a standard that makes it easier....Thanks in advance.
At the very least every product/object whatsoever needs a foreign_key in its table, as for example the user's id. This is necessary and sets the relation from the product/object with the user.
And then it depends on how complex you want your system to become. An easy way would be to just use boolean columns in the user table, like an admin, an editor column and so on, with only true and false as values. In your code you could then use if and case to check if a user is an admin and show him parts of your app or not. Like a delete link for example. But you could also restrict updating and deleting to people whose user has a true value in the sufficient column.
The more complex route would include other id-fields in the tables which set a relation of something to something else. Like say you want the user to be a seller or a buyer, then you would add seller_id and buyer_id columns to the products table and check if the ids correspond with the user_id. But not "the" user_id, but a different user_id which you saved when the user created the product listing for example. This way you could guarantee, that besides your staff the user who created this thing has rights to edit it, too, because of the product's user_id being the same as his user_id (current user) when he is logged in to your system.
You could do even more complex relations but then you'd have to create another table and save other ids in it which relate certain users with say other users. In this table you save let's say a maintainer_id and a maintained_id, both have values of certain user_ids but this way you could make a relation between objects one user could change, though they belong to others. Or if you're talking of customers so the mainter_id would be allowed to write messages to those people with maintained_id, like if someone is a seller and the others are potential buyers.
I'm having a little trouble understanding exactly what you're looking for. From what I've gathered, it seems you want a database that holds permissions, users, and departments. In this very basic example I've created 3 tables. (assuming one user can only belong to one department)
You could set a foreign key in the users table which links to the primary key in the permissions table. The departments table would have the foreign key of the user_id.
You could base all of the logic on what each permission can do with your queries and application side logic.
(I can't embed images due to not having 'enough rep')

PHP-MySQL - allow client to define process, algorithm or query

In my website, I allow groups of users to manage a group bank account. Users report that they payed for something the group should fund, and the group account 'pays them back'.
However, I want to give the account admin control over which user pays what and when.
For example, a group of people share a car. They open a group account to handle their car-related expenses - gas, maintenance etc.
The group admin decides that only people who drove over 20 miles this month should participate in the gas bill, and the bill is divided between the paying users (those who drove over 20 miles) proportional to their mileage (a user who drove 60 miles will pay twice as much as a user who drove 30 miles).
I have a table for users (a list of users, each one is part of a group account), one for group_accounts and one for expense_types (in this example, gas and maintenance are listed here)
The question:
Is there a good way to store client-defined queries or algorithms in a database to allow the admin of the group to create complex billing methods, and (using PHP) subsequently retrieving and implementing those algorithms and calculating the result?
This is a database design question, so as far as I'm concerned extra columns may be added to any table, new tables created, procedures, triggers etc.
NOTE: THE SPECIFIC EXAMPLE IS OF NO REAL INTEREST, I want my system to handle algorithms of unknown complexity that use data from unknown tables and columns.

How to make a User Privacy Table in MYSQL

I am working on a social networking website in which I have idea of creating groups, events and friend list. I want user privacy for his friends like as given below :
1. User can select friends who can view his personal info or who can't.
2. User can manage who can see his events and groups and who can't.
I have designed a table structure for the same that I am pasting below :
User_location_id
User_id
Allow_friends(ids separated by comma)
Deny_friends(ids separated by comma)
Allow_groups(ids separated by comma)
Deny_groups(ids separated by comma)
Allow_search
(Chapters of State,City)
Friends
(Visible to Some, Hide from Some) ( if 0 then I am geeting friends ids from allow_friends else Deny_friends)
Groups (Visible to Some, Hide from Some) ( if 0 then I am geeting friends ids from allow_groups else Deny_groups)
Privacy_for_type
Privacy_for_name
Should there be any other structure that will be efficient and can minimize database hits and don't make database intensive.
If you're going to design database tables, you might want to read about normalization:
http://en.wikipedia.org/wiki/Database_normalization
Storing ids separated by commas makes it difficult to update those records and to prevent duplicates. I'd recommend your allow and deny columns be split into separate related tables. This will not make it any more database intensive as you'll still only need one query, it just means you might have to have a query with a join.
I'd recommend using two (or three) tables, separating users + groups, and permissions.
The users/groups table can contain information specific (and isolated) to the user/group (so #'s 1 and 2 for the user) and then you can add a field for "type" or "category" that says if it is a user or group. If the information you're storing for users and groups are different enough, you can just have separate tables for each.
The permissions table can contain any permissions, including #'s 4-9 on your list (I don't really know the context of 10/11.) The table can also be use to manage group membership. The following is an example of how you could structure the permissions table:
permid: arbitrary unique primary key auto_increm column
asset_cat: the category (or table name) to which the asset belongs
asset_id: the userid, groupid, etc. for which the permission describes
uid: The user who is seeking permission
permission: the permission being sought for the asset_id by the uid
value: the value of that permission
Some example entries:
//Same as listing 1338 in user 1337's Allow_Friends Field
1002, 'user', '1337', '1338', 'Allow_Friends', 'True'
//Lists 1337 as a member in group # 43
1003, 'group', '43', '1337', 'Member', 'True'
These are just some examples to help you get started. Let me know if this was helpful, or if you need me to clarify anything :)

Permissions to view Entries in MySQL Database Front-End

I've got a PHP/HTML/Javascript driven front-end for a MySQL database which archives different files/papers for our office (kind of an electronic index for physical paperwork).
The users want to be able to have permissions on each of these entries; for instance HR complaints need to be indexed, but should not be viewable by all users of the database.
The user heirarchy is two-tier. Each user is a member of one OR MORE distribution lists (similar to an Email list). When a file is indexed, the user choses the permissions for others: for instance he/she can select the following for a sample HR complaint:
List | Permission
`````````````````````````````````
HR Dept | Read/Write
Board Members | Read
John Smith | Read/Write
Mary Smith | Read
and should be invisible to anybody else. Now I've tried several things to implement this, the most recent being a relations table which relates the following:
User 1->Many DistributionList // Assoc the user to some lists
Permission 1->Many DistributionList //Indicates level of permission that the list has
Permission 1->Many User //Indicates level of permission for each user
However the permission table contains a row for each file for each permission, which, given a few thousand files and ~50-60 lists/users, means a few hundred thousand entries. Since this index will not be flushed often (maybe flush files older than 50 years) that number could skyrocket. Not to mention that the queries are somewhat complicated, and take a decent amount of time (~1 second for the SQL request) for only a couple hundred files.
Is there a more efficient way to create this sort of User based stuff? Is it possible instead to make users in SQL itself with these permissions and let the connection handle these things?
tl;dr: What is the best way to put read/write/invisible permissions on entries in MySQL using PHP, Javascript, HTML and PHPMyAdmin?
If there are not many groups (64 max) you could use a SET of permissions for each file (1 extra column).
http://dev.mysql.com/doc/refman/5.0/en/set.html
So each file could have one column denoting which groups it belongs to, which can be expanded as the systems grows.
You could also add a second column if you want to go beyond 64, but that would require more complex queries (keeping departments separate would help here, HRgroups, Boardgroups etc..)
You could also add exceptions to specific users or create another group. But as you say one associating entry per file/user is the best your going to get.

Categories