Skip to main content
GameDev.net gamedev.net
🔒 Locked

[web] User permissions

Started by Fuzztrek Feb 5, 2006 at 7:07 PM 2 replies 1.2k views
Original Post
Fuzztrek
Fuzztrek
It was interesting for me to see a thread on user permissions here, when I've been contemplating that same issue myself. (note: I thought of posting in the Web App Design: Storing Settings thread, but decided to create a new thread to avoid any potential hijacking.) Currently, my permissions system works like this: A user attempts to access an item of content in a particular way (either by viewing, adding, editing, or deleting). I compare the meta data about the content being accessed to the user's stored abilities to determine whether or not the action is allowed. The content meta data contains: type: e.g., news item, forum post, forum thread, etc permission hint(s): e.g., "Authorized Only", "Registered Member Only", etc The user abilities contains: power: how the content is being accessed (view, add, edit, delete) type: type of content permission hint set(s): a hint and flag denoting whether the hint is required, restricted, or optional. This allows for a great deal of flexibility - you can specify, for example, that a user can only view news items without permission hint authorized only. Or you could specify that a user can add news items, but all news items created must have permission hint member only associated with the item. Unfortunately, due to the complexity of this, I have to sort out whether or not a user can access content in PHP (opposed to sorting it out in an SQL query). For many things, like say accessing a single article, this isn't a problem. But if I were to pull up a list of one hundred or so news items, I have to go through each item one by one to determine whether or not a user has access. Although this hasn't been slow in the past, it has been very inconvenient - especially when I would like to, say, limit a query to the 5 most recent articles. If the first three happen to be articles that a particular user cannot view, only two will be displayed (even though there may be many more viewable articles in the database). My tables are set up like so (abilities, hints, and powers are merely two field tables containing an id and name): Generic Asset table for content: asset_id type_id Ability-Hint relation: ability_id, hint_id, flag (Required, Restricted) -- if the hint/ability relation is not present, that hint is optional (not required, not restricted) Ability-Power relation: ability_id, power_id Ability-Type relation: ability_id, type_id Ability-User relation: ability_id, user_id Asset-Hint relation: asset_id, hint_id A visual aid to help illustrate how a user and an asset come together in the database (note that power would most likely be a constant in the equation):
So basically, the trouble I'm having is comparing the content hints to the user's ability hints in a query. Assuming the user can view/add/etc. the specificed type, he/she can proceed as long as his/her Required hints are associated with the content and his/her Restricted hints are not associated.
Sander
Sander
Under the assumption that you do not have thousands of assets and thousands of visitors, you could simply query all the articles in the database and then keep checking them in a loop untill you have 5 that are viewable:

result = Query all articlesarticles = arraywhile (sizeof(articles) < 5 and article = next_row(result)){  if allowed_access(user, article)    push(articles, article)}


It's not too friendly on the database, but unless you have loads of assets and visitors, it'll be okay. If you are dealing with large ammounts of assets and visitors then you might want to redesign your system in a more database-friendly way. Your system offers a lot of flexibility, but do you really need that flexibility? I doubt it. Design according to what you need.
konForce
konForce
I don't quite understand exactly what you mean, but it is possible to build a user model that is so flexible that it becomes impossible to realistically use. You can either:

  1. Not worry about it and hope you have enough free cpu left for it to work...
  2. Cache the results - very tricky for this particular application
  3. Change your model to be easier to use

A system that I've found to be very flexible, but easy to manage is this:

  • Tasks define something that can be done: NewsPost/Edit, Poll/Create, etc.
  • Roles group a set of logical tasks together and are given real world names: News Editor, Moderator, etc.
  • Users are assigned Roles.
  • Groups are assigned Users and used to further limit access.

If you wanted to pull back the list of 100 articles the user has access to, you'd first check to make sure he had the Task of "NewsPost/View." (His Role doesn't matter. You just want to make sure he has the ability to view news posts in general.) Then you check to make sure he belongs to the Group that the News Post does. That can easily be managed in a joined query:
SELECT DISTINCT p.* FROM news_post AS pJOIN news_post_group AS ng ON ng.post_id = p.id JOIN user_group AS ug ON ug.group_id=ng.group_id AND ug.user_id = $USER_ID

That assumes each news article can be assigned to multiple groups, and each user can be assigned to multiple groups as well.

The other type of security you would need is:

  • one-to-one (author mode): simple owner_id in the table does the trick
  • private users: only small number of people (without regard to group) can access the asset. These don't happen too frequently, but they can easily be solved with a simple two column "asset_user" table to go along with the main "asset" table.


Generally speaking, you have world readable content and member writeable content if and only if they have permission to that asset type. It is also common to have things that only a subset of members can view (A Moderator-only forum).

The reason the group concept works so well is that the "Asset 1:many Group" tables stays constant even when new users are added to the group. You simply add the user to that group and he can immediately access all the data. If you try to give each user his own set of permissions, you'd have an incredible amount of look-up data needed to do it properly. Without that data, you'd be looking at a code-level solution as posted above.

Personally, I'd look to make it more manageable and give up some flexibility.
Fuzztrek
Fuzztrek
Thanks for both responses!

The thing that seems to be making my system so complex is the Hints. If I were to combine hints and asset type together, I would be able to use a much less complex query, like the konForce is using. (Or actually, I could just limit each asset to a single permission hint, to avoid an abundance of types.) It wouldn't be as flexible when it comes to multiple hints, but it would be a lot more intuitive and much faster.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.