Contents
See also
The Keyring
[API]
class is the core class that is responsible
for handling most permission checks in BASE. A keyring object
is created when a user logs in using the SessionControl.login()
method. The keyring holds information about:
Project
:s [API]
the user has access to
The information in the keyring is reloaded by a timer at regular intervals specified
by the permission.timeout
setting in the base.config
file. The default value of this setting is 10 minutes. The information can
also be forced to be reloaded by a call to the SessionControl.reloadPermissions()
method.
The keyring object is not available directly to the rest of the application.
All access to the keyring is handled by the SessionControl
. We do not
list all methods for the Keyring
class, since most of them are similar and
have the same names as those in the SessionControl
.
The Permission
[API]
enumeration defines the permissions available in BASE.
Each permission is represented by an integer value (grantValue()
)
that is used when saving permissions in the database. To combine several
permission the values can be OR-ed together using the | operator. The values
are also constructed in such a way that some permissions implicitly includes
other permissions, for example the WRITE
permission includes the
READ
, USE
and RESTRICTED_WRITE
permissions. See the Javadoc for the permission class for more information.
There is also a denyValue()
associated with each permission. This value
can be said to be the inverse of the grantValue()
value, because
the following calculation will effectively remove all denied permissions from
those that have been granted: granted & ~denied
(granted AND NOT denied).
For example:
int granted = Permission.grant(Permission.DELETE); // granted = 31 int denied = Permission.deny(Permission.WRITE); // denied = 120 int combined = granted & ~denied; // combined = 7 --> Permission.RESTRICTED_WRITE
Each BasicItem
[API]
has an internal permissions
variable
which holds the logged in users permission to manipulate the item. This value
is initialised based on the information in the keyring object. In theory, we
could have done well without the permissions
variable and always
do permission checks directly with the keyring object, but for performance
reasons we chose to cache the permissions in each item.
Since it is the DbControl
[API]
that is responsible for creating, loading, saving,
deleting, etc. items from the database, it is also the DbControl
that is
responsible for initialising the permissions. This is done by a call to
the BasicItem.initPermissions()
method. The
Item handling document includes code examples
which shows exactly how the DbControl
initialises the
permissions.
The default implementation of the initPermissions()
method
in BasicItem
will use the SessionControl.getRolePermissions()
to find the permissions the logged in user has been granted based on role
membership. The OwnedItem
[API]
class grants additional permissions
if the logged in user is the owner of an item, and the SharedItem
[API]
class grants additional permission if the logged in user has an item or project
key with permissions for the item. The ChildItem
implementation
assumes that an item has a SharedItem
parent item and uses
those permissions to get the permissions for the child item.
Subclasses that need to grant or deny additional
permissions must override the initPermissions()
method.
For example the News
[API]
class will grant read access to everyone
(even if no user is logged in) if the current date is between the start and end
date of the news item. The Role
[API]
and Group
[API]
classes are other exemples which grant read permission if the logged in user
is a member of the role or group.
As a general rule, if the subclass extends from the OwnedItem
,
SharedItem
, ChildItem
or some other subclass to those classes,
it is usually
not necessary to override the initPermissions()
method. If it
extends directly from the BasicItem
it is more likely that
the method must be overridden.
Checking the permissions for an item is very easy. Either use
the hasPermission()
or the checkPermission()
method.
The difference is that the checkPermission()
method throws a
PermissionDeniedException
while the hasPermission()
returns a boolean.
The two methods are implemented and tagged as final by the BasicItem
class. This is because we don't want subclasses to override these methods. If
a subclass needs to grant or deny permissions, the initPermissions()
method should be overridden.
The various subclasses to the Key
[API]
class are used to store the actual permissions in the database. There are three subclasses:
The database contains one role key for each item type, created during the initialisation of the database. The number of role keys remain fixed. No new ones can be created and they can't be deleted. Each role key may link a role to a permission code, effectively granting those permissions to all users that are members of that role.
// Grant CREATE permission for FILE:s to a role Role r = ... DbControl dc = ... RoleKey rk = RoleKey.getByItemType(dc, Item.FILE); rk.setPermissions(r, EnumSet.of(Permission.CREATE)); dc.commit();
Note that role keys are never assigned to a particular item. They always
apply to all items of a given type. If the DENIED
permission
is set it overrides all other permissions.
Item keys seem similar to role keys, but they are very different.
To begin with an item key is assigned to a Shareable
item using
the Shareable.setItemKey()
method, thereby granting users/groups
access to that particular item. It is possible to specify the same item key
to several items. In fact, once an item key has been created it can't be
changed, so the core tries to avoid creating duplicate item keys (ie. item keys
with exactly the same user/group/permission combination) by reusing
existing item keys. The item key has no set
methods to change
the permissions. Instead you have to use the helper classes,
UserPermissions
[API]
and GroupPermissions
[API].
Project keys work in exactly the same way as item keys, except that
they share items to projects instead of to user and groups.
To set the permissions you use a ProjectPermissions
[API]
object.
There is,
however, another dimension to projects keys. Members of a project has
a permission associated with that project, which is the upper limit
for access to items in that project. For example, a user is a member
of a project with USE
permission (the recommended permission),
and we have two items shared to the project, one with READ
permission
and the other with WRITE
permission. The user's permissions
to those items are READ
and USE
respectively.
Another project member with DELETE
permission in the project
will get READ
and WRITE
permission to the items.
Project keys are only loaded for the currently active project which is set
by calling the SessionControl.setActiveProject()
method.
And, if a project is active, the core will share new items to that project
automatically.
The MultiPermissions
[API]
class is not shown in the diagram. It is a useful helper class to modify
lots of permissions to multiple items at the same time, while keeping those that
has already been set, even if the logged in user doesn't have access to all
other users, groups or projects.