Branch Permission Manager
The Branch Permission Manager is a service which keeps track of branch permissions:
- Branches creation can be allowed for only a specific set of users.
- Read and Edit permissions can be managed for each branch and user.
- This applies to both MDX queries (read permissions) and Datastore REST API calls (create/read/write).
Branch permissions model
Only a specific set of user is allowed to create a branch, they are called branch creators.
Each branch has a set of owners and readers.
Owners can read and edit the content of a branch, update the permissions of the branch or even delete the branch.
Readers can only read the content of a branch.
To indicate that all the users are allowed in a specific role (reader, owner or creator),
the constant IBranchPermissions.ALL_USERS_ALLOWED
can be used.
In the Datastore REST API the string __ALL_USERS__
can be used.
This string is a reserved keyword and can therefore not be used for other purposes.
Additional default permissions must be defined when creating a Branch Permissions Manager. These defaults are used as a fallback when querying a branch that exists in the datastore, but which was not registered in the Branch Permissions Manager. This could happen if the branch is not created through the datastore service. These defaults are useful to not be stuck with a branch without permissions, but are not optimal as they are not branch specific. It is therefore highly recommended to only create branches through the datastore service, providing branch permissions at creation time.
Interaction with Datastore REST API
Each query sent to the Datastore REST API interacts with the Branch Permission Manager to determine the permissions of the current user.
Having the read permissions on the branch does not mean the user can read everything on said branch: it is still intersected with the stores and fields permissions. To read the data a user needs both the branch permission and the field permissions. The same thing happens for the write permissions: a user needs both to be owner of the branch and have the write permissions on the field to update anything.
Only branch creators are allowed to create a new branch. The creator can specify who are the owners and the readers of the new branch. If no permissions are specified, the current user roles and username will be set as both owner and reader.
Interaction with MDX queries
Each MDX query is filtered by the Branch Permission Manager to only allow content that is visible by the current user. This means that only the branches where the user has read permissions can be queried.
In the case of real time, if a query is registered on several branches, it is updated for each new branch created.
Configuration
Both ActivePivotConfig
and DatastoreConfig
require an IActivePivotBranchPermissionsManagerConfig
.
This configuration provides an IBranchPermissionsManager
, which is required to create the Active Pivot Manager
and build the Datastore.
The sandbox provides an example, where the branch permissions are retrieved from the Content Service
(but with a cache that allows not to query the Content Service for every query).
See FullAccessBranchPermissionsManagerConfig
for the construction of the permission manager based on the
Content Service, and for the wrapping of that manager in the cache. The actual implementation used in the sandbox,
ActivePivotBranchPermissionsManagerConfig
, is an example of how to override the default permissions of
FullAccessBranchPermissionsManagerConfig
to benefit from the content service / cache behavior
without allowing full access to all branches:
/**
* Sandbox configuration class creating the manager of branch permissions.
*
* @author ActiveViam
*/
@Configuration
public class ActivePivotBranchPermissionsManagerConfig
extends FullAccessBranchPermissionsManagerConfig {
@Override
protected void setUpMasterPermissions(
final ContentServiceBranchPermissionsManager contentServiceBranchPermissionsManager) {
// allow only admins to write on the master branch, and use open read permissions (no
// read/write restriction for any user)
contentServiceBranchPermissionsManager.setBranchPermissions(
IEpoch.MASTER_BRANCH_NAME,
new BranchPermissions(
Collections.singleton(ROLE_ADMIN), IBranchPermissions.ALL_USERS_ALLOWED));
}
@Override
protected Set<String> getAllowedBranchCreators() {
// Here, admins and users can create new branches.
return new HashSet<>(Arrays.asList(ROLE_ADMIN, ROLE_USER));
}
@Override
protected Set<String> getDefaultBranchOwners() {
// Only admins can edit branches, unless specified so
return Collections.singleton(ROLE_ADMIN);
}
}
BranchPermissionsManager
is a simpler example that does not rely on any storage
(permissions for each branch stored in a map).
It is mostly used for tests when we don't want to build a full content service, and is as simple to use as:
final IBranchPermissionsManager bmp =
new BranchPermissionsManager(
Set.of(ROLE_ADMIN, ROLE_USER), // Branch creators
Set.of(ROLE_ADMIN), // Default branch owners
IBranchPermissions.ALL_USERS_ALLOWED); // Default branch readers
// The BranchPermissionsManager has a default security for the master branch (all users can read
// and edit),
// but it is highly recommended to redefine it :
bmp.setBranchPermissions(
IEpoch.MASTER_BRANCH_NAME,
new BranchPermissions(Set.of(ROLE_ADMIN), Collections.singleton(ROLE_USER)));