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.
Related
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.
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')
I have a simple document management system which currently offers "public" access to documents based on a company id - I would like to implement access controls on a user by user basis. I am happy with how to check access rights etc in PHP but not sure how best to maintain approved users in the table in an efficient way.
A document could have public access or private access restricted to x users and as I don't know the value of x it doesn't make sense to implement multiple fields in MySql called user1, user2 etc.
There is a table already called users and one called documents. Would a new table called users to docs make sense or is there a better way to implement this so I can check if a user is entitled to access the document if they attempt to?
Best method is to have link tables, e.g.
table #1: users (id, ...)
table #2: documents (id, ....)
and
table #3: user_documents (user_id, document_id)
where user_id and document_id are foreign keys pointing at the users and documents tables
If a record exists in user_documents, then the user has access to the document. If you need to implement various levels of access (read/write/etc..) you'd store that in the user_documents table as well in extra fields.
By comparison, if you had something like
table #1: users (id, doc1, doc2, doc3, etc...)
where the doc# fields point at documents this user has access to, you'd have to have N fields in the table to handle permissions for N documents. If only a few users have rights on N docs and most have far fewer, you'd be wasting a lot of space on unused fields. And there will always be some joker who requires N+1 documents, meaning you're modifying your tables every time.
With the link table, you only have 2 fields, ever, and only as many records as there are user/document access pairs.
Current project I am working on is a web application, that has to be delivered to multiple customers on their own servers. The website needs a permission control system, that will manage areas and features users can or can not use.
As for know, I'm designing a database-driven permissions system, with permissions stored in database. Every user has a role. The role defines the list permissions available. The schema looks like this:
users table
1. user_id
2. name
3. role_id
roles table
1. role_id
2. name
permissions table
1. permission_id
2. name
roles_permissions table:
1. role_id
2. permission_id
In the code I would fetch logged users role and permissions, and check if the user is able to perform action or see area like so:
if($user->hasPermission('Edit HR')) {
// let user see the editing HR section
}
The hasPermission would check if user has a permission with a name 'Edit HR' and will return the needed result. The problem I see is the database table has to have the permission record with a name being exactly 'Edit HR', not 'Edit_hr' or 'HR Editing'. So I have to make sure the data for the permissions system is the same for every database the applications are using. Which kind of makes me think this is a flawed design and needs to be re-designed. Creating new sections and features would also require to update all the databases, which also makes me a sad panda.
So, basically, the question is: what is the best way to design the database driven permission system and keep the database integrity on multiple databases?
The scheme you've come up with looks fine. The only thing I would add to that is on the permissions table I would add a field called tag or similar.
The permission tag would be something like EDIT_HR, and you would use this as the reference in your code instead of its name. Use the name just for display purposes for example HR Editing. This way the name can vary as required, and it won't affect your code.
The solution I'm using is to have a global $current_user object that reads the permissions table on creation and stores all permission actions that are valid for it. This array is then searched whenever you need to check an action. It saves on DB queries, although if there are security implications for storing this kind of data in a global object, I haven't found it.
There's only 1 db table required (sample):
user_id | user_role | user_action
---------------------------------
0 | 10 | view_dashboard
0 | 1 | view_users
User role corresponds to the minimum user type (Admin, editor, visitor, etc.) so all actions with a user_role >= $current_user role are available. The user_id column allows you to override certain levels for a specific user.
With this kind of setup, it's also easy to have a page that lists all permissions and allows a user to modify the value with a simple dropdown (but make sure not every user can do that).
I have a php/mysql application. There are users who have folders. Folders can only be one level deep. Each folder can have unlimited number of documents. The relevant tables are as follows:
user_table:
user_id(PK), name, password, etc
folder_table:
folder_id(PK), name, user_id(FK into user_table)
document_table
document_id(PK), user_id(FK), folder_id(FK), date, name, etc
All queries to operate on folders and documents are of the form
select/update/insert <blah, blah, bhah>
where user_id = %d
Now, I'm looking to allow users to share they folders with other users. I want to do this in the least disruptive way possible. I also want to minimize run time overheads of resulting WHERE clause.
I've been wracking my brains and googling but haven't found a simple enough solution. I can think of implementing it in a manner similar to unix's (read, write, execute) along with (owner, group, others) mechanism. But it seems a bit too complicated for my humble system.
I would really appreciate if someone could give me pointers as to which approach I could possibly take. My goals are simple:
The system doesn't require a whole lot of reworking
At a minimum users should be able to share folders with other users or groups (I
will add concept of groups if needed)
There should not be too much overhead in SQL statement's WHERE
clause as opposed to what it is now (as simple as: WHERE
user_id = %d)
Sharing folder(s) with user(s)
You can to add a table *folder_user* with columns folder_id(FK), user_id (FK)
The user_id in *folder_table* represents the owner of the folder. When the owner shares this folder with another user, you add folder_id and user_id (with whom folder is shared) into folder_user table.
Later, you can add column access (enum 'READ', 'READ_WRITE') to the same table, to see if a user is allowed to edit documents in the folder or not.
Sharing folder(s) with group(s)
You need a table group
Then you need to add users to groups, so add a table *user_group* : user_id(FK), group_id(FK)
Then, to give access to of a folder to a group add table *folder_group*: folder_id(FK), group_id(FK) to give access for a folder to a group.