Here is a description of the permissions system used in Fluidinfo. Some terminology and things to bear in mind:
There are two things in Fluidinfo that are subject to permissions control: namespaces and tags. These are treated in a uniform manner.
Users attempt to carry out actions on namespaces and tags.
When Fred decides to rate something, say with a 6, a tag with that value is created and attached to a Fluidinfo object. If he later rates another object as a 3, another fred/rating tag is created and attached to the other object.
For the purposes of permissions checking, Fluidinfo considers what we'll call the tag itself to be different from the set of its occurrences on objects. Using Fluidinfo permissions you could, for example, grant permission to others to alter occurrences of fred/rating (e.g., change a 3 rating to a 4), but not permission to alter the tag itself (e.g., its description).
Permissions are checked every time an application, on behalf of either a user or itself, uses the Fluidinfo API to attempt to perform an action on a namespace or tag.
To denote the object that corresponds to a namespace or tag, e.g., fred/rating, we will use OBJ(fred/rating).
In case you are asking yourself about permissions on objects: Objects in Fluidinfo have no permissions.
The available actions on namespaces are:
The available actions on a tag itself are:
The available actions on the set of occurrences of a tag are:
The permission for each action are implemented as a policy (set to either "open" or "closed"), and zero or more exceptions to the policy. An API call is allowed to proceed if the permission for the action is either
Permission information for namespaces and tags is stored in instances of other Fluidinfo tags. That is, Fluidinfo uses (other) tags to store permissions about namespaces and tags. This is a conceptually simple approach, but it needs some care when thinking about changing permissions - who has permission to change a permission? We'll answer that below.
Permission tags live under the following Fluidinfo namespaces:
For each action for each of these categories, there are two corresponding tags: one for the policy and one for its exception list. For example, permission information about who can create a tag in a namespace is stored in instances of the two tags
So those are the tags involved in permissions checking. But what about the occurrences of those tags, encoding access to a specific namespace or tag?
Instances of the permission tags are stored on objects that corresponds to the namespaces and tags. E.g., the permissions information for a tag fred/rating is stored in permission tag instances on OBJ(fred/rating).
To be more concrete, suppose a user is trying to delete the tag fred/rating. Fluidinfo will examine the tags fluiddb/tags/permission/delete/policy and fluiddb/tags/permission/delete/exceptions on OBJ(fred/rating) for the open/closed policy and its exceptions.
As a second example, suppose there is a namespace fred/books. The object associated with it, OBJ(fred/books), will have tags fluiddb/namespaces/permission/create/policy and fluiddb/namespaces/permission/create/exceptions on it. The values of those tags indicate which Fluidinfo users are allowed to create namespaces or tags in fred/books. Similarly, OBJ(fred/books) will also have instances of fluiddb/namespaces/permission/update/policy, fluiddb/namespaces/permission/update/exceptions, etc., for each of the other actions relevant to namespaces.
Note that the permissions for a tag itself and the permissions for its occurrences are both stored on the same object. There is no possibility of collision because the tags holding permissions for the tag itself are under the fluiddb/tags/permission namespace while those for its occurrences are under the fluiddb/tag-values/permission namespace.
When taking an action on a tag, we have to consider whether it is a permission tag. In the simple case, when it is not a permission tag, Fluidinfo decides whether to allow the action using the normal policy/exception permissions tags as described above.
Otherwise, the user is trying to change a permission tag. Here we do not use the regular permission system to hold information about permissions because that would be circular.
Instead, to check whether a user is allowed to alter a permission tag, two other policy/exception atttributes are consulted. These are the permission control tags, located alongside the regular permissions tags in the namespaces
That means that there are really two kinds of permission tags: regular and control. We need to consider how instances of these two types can be changed.
When a user attempts an operation on a regular (non-control) permission tag under any of
In these cases we consult the policy and exception list given by the instance of the control tag on the same object.
When changing a policy from "open" to "closed" on a non-control permission tag, the instance of the exceptions tag is set to the empty set. It is probably an error to leave a non-empty exceptions list intact: the point of changing a policy from "open" to "closed" is to keep users out by default, and that policy should definitely apply to the users who were already excluded. Leaving the exceptions list intact would be granting permission to those who were formerly explicitly excluded due to the previous "open" policy.
Similarly, when changing a policy from "closed" to "open", the instance of the exceptions tag is set to the empty set. Users who were on the old exceptions list (i.e., who had access) should continue to have access. Not clearing the exceptions list would deny them access under the new "open" policy.
When a user tries to change a permission control tag, we simply check the policy and exceptions list of the control tag.
That means that a user who has control over a namespace or tag can remove/grant control over that thing for others. It also means that a user with control can remove themselves from the group of users with control.
The comments about clearing the exceptions list when a policy is changed on a regular permission tag also apply to a control permission tag, but with one variation.
If a control policy is changed to "closed", the user making the change is added to the exceptions list. This is legitimate, seeing as that user must have originally had control to even be making this change. We are simply preserving that user's control. If we did not put the user into the exceptions list, no-one would be able to control the permissions on the namespace, tag, or tag instance set.
It is still possible for someone with control to take away control for everyone, including themselves. They just have to set the policy to "closed" (if it is not already) and then remove themselves from the exceptions list. Note that this might be a desirable state of affairs. For example, one could put a tag on a number of objects and then set permissions so no further occurrences of the tag could be created by anyone. You would do this by first setting the policy of the create action for the tag to be closed, with no exceptions. Then, set the policy for the control permission of the tag to be closed. Then remove yourself from the exceptions list of the control tag. At that point no-one has permission to add the tag to objects, and no-one has the right to change that permission list. If the permissions tags are readable, others can verify this fact.
When a user creates a new namespace or tag, the policy and exceptions for each of the relevant permission actions are copied from tags on the user's own object onto the object created for the new namespace or tag.
I.e., we copy the values of fluiddb/namespaces/permission/create/policy and fluiddb/namespaces/permission/create/exceptions etc., for all permission tags from the user's object into new occurences of the same tags on the newly-created object created for the new namespace or tag.
When a new user is created in Fluidinfo, a set of permission defaults is set for them. These are the permissions that will be used on the namespaces and tags that the user creates in the future, as just described.
The values for system-wide default permissions for new users, are found in fluiddb/default/namespaces/permission/create/policy and fluiddb/default/namespaces/permission/create/exceptions etc. tags on the system administrator's object and are copied into the corresponding tags fluiddb/namespaces/permission/create/policy and fluiddb/namespaces/permission/create/exceptions etc. that are placed onto the freshly-created object for the new user.
Here is a list of all permissions tags. As described above, these tags appear on the objects for all users, namespaces, and tags.