All the permission management is based on groups and permissions that are given to those groups. So first of all there should be several predefined groups:
- Blocked/Banned Users
- Registered Users
When a user registers at the forum, he starts to be a member of the Registered Users, then when he activates his account, he is also added to the Activated Users group. Then he can be assigned to the Moderators group or be banned or anything else that can be achieved by creating an ad-hoc group.
Each group has a different set of permissions and restrictions, but if at least one group contains some particular permission (let's say adding topics), then the user is allowed to do this. And vice-versa: if at least one restriction was found for an action, then it outweighs all the permissions (you can consider a user that was allowed to create topics was added to the Banned group with restrictions that do not allow to create topics anymore). So by adding or removing from such groups we define what users can or cannot do. In practice the configuration of permissions will contain more items, but for demonstration it should be something like this:
As you can see, the admin permissions will allow everything, while the simple Registered Users permissions will be neutral which means they neither allow, nor restrict actions.
Now, each branch will have its Permission Schema which defines what groups of users can do this or that action:
- VIEW_TOPICS - user can see branch in the list of branches, can browse it and read topics. This is a basic permission and if user is not granted with it, then it can't do anything else in the list. Note, that user can't see branches he doesn't have VIEW_TOPICS for in any lists. Also if all the branches in the section are hidden (user doesn't have VIEW_TOPICS for them), he also can't see that section in any of lists.
Additionally posts in any of searches (topics search, recent activities, rss, user's posts) shouldn't appear if they are in the branches user doesn't have VIEW_TOPICS for.
- CREATE_POSTS - user can create topics/posts/polls in the branch.
- CREATE_STICKED_TOPICS - user can create topics that are sticked to the top of branch and they are shown first in the branch. User can do that only if he has both CREATE_STICKED_TOPICS & CREATE_POSTS.
- CREATE_ANNOUNCEMENTS - user can create announcement topics which are sticked to the top of branch and also has a label Annoncemnent. User can do that only if he has both CREATE_ANNOUNCEMENTS & CREATE_POSTS.
- DELETE_OWN_POSTS - user can delete his own posts in branches he has VIEW_TOPICS permissions for. It's not enough to have this permission to remove topics where other users already posted as well.
- DELETE_OTHERS_POSTS - user can delete posts left by other users. Also in conjunction with DELETE_OWN_POSTS he can delete topics both left by him and by other users. He can't remove topics where he posted if he doesn't have DELETE_OWN_POSTS permissions.
- EDIT_OWN_POSTS - ability to edit posts/topics/polls left by user himself. It's possible to edit posts even if user doesn't have CREATE_POSTS anymore.
- EDIT_OTHERS_POSTS - user can edit posts/topics/polls left by other users (even if he doesn't have CREATE_POSTS for that branch). This doesn't give him right to edit his own posts.
- MOVE_TOPICS - user can move topics from the branch (branch1) he has permissions for to another branch (branch2) (he needs to have only VIEW_TOPICS permissions in order to see branch2, if he doesn't have such permissions, he can't move topics to it)
- CLOSE_TOPICS - user can close topics so that others can't answer to it anymore. Users that have this permission for the branch still can both open topic again or post an answer even if the topic is closed (unless he doesn't have CREATE_POSTS). This doesn't affect voting functionality of polls, users still will be able to vote.
Justification for Neutral permission state
Want to describe why I think we can't survive without Neutral - a state when group is neither in Allowed section, nor in Restricted one.. So want to show 2 use cases. Let's say we don't have Neutral, so we have only one flag in the db:
- If the presence of flag means 'the action is allowed', then if we're talking about Banned Users which are not allowed to post in branch, we don't have a way to take away that permission, because user is still in other groups that actually allow to post.
- If the flag absence means 'the action is restricted', then we can't restrict access hidden branches, like only for Moderators, because in this case we need to explicitly restrict access to all the groups besides Moderators (let's say there are dozens of groups, this becomes nightmare).
So to let these 2 use cases co-exist in a single application, we need to have another state: Neutral, which is default. In this case if we're talking abut Banned users, then this is the only group that has Restricted flag to post which crosses all the 'allowed' flag of all other groups (no matter how many groups allow that action, if at least one group is restricted, then the action is not allowed). And vice versa, if we're talking about Moderators and their hidden branch, we need to allow actions only to one group - Moderators, all others will stay Neutral (which is not allowed and not restricted). So there are eventually 3 states:
- Access is not allowed if user is not a part of any Group to whom this action is allowed
- Access is allowed if at least one group is allowed to perform it.
- Access is not allowed if at least one group is restricted, no matter how many others are allowed.