Chapter 10. Kernel Tutorial

This chapter discusses how to use permissioning and domain objects, answers frequently-asked questions about the WAF security mechanisms and API, and touches on extending the authentication system. Please refer to Chapter 4 WAF Component: Kernel for more information about the concepts used in these tutorials.

10.1. Permissions Tutorial

10.1.1. Granting Access

Granting access to a party is accomplished by creating a PermissionDescriptor and passing it to PermissionService.grantPermission. The following example grants read privilege on MyACSObject 50 to Group 5:

import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PermissionDescriptor;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.OID;

OID acsObject = new OID("example.MyACSObject",
new BigDecimal(50));

OID party = new OID("com.arsdigita.kernel.Group", new BigDecimal(5));


PermissionDescriptor perm =
new PermissionDescriptor(PrivilegeDescriptor.READ,
acsObject, party);

PermissionService.grantPermission(perm);

The next example grants admin privilege on all objects to User 100:

import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.UniversalPermissionDescriptor;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.OID;

OID party = new OID("com.arsdigita.kernel.User", new BigDecimal(100));


PermissionDescriptor perm =
new UniversalPermissionDescriptor(PrivilegeDescriptor.ADMIN,
party);

PermissionService.grantPermission(perm);

10.1.2. Revoking Access

Revoking a privilege on an object from a party is accomplished by creating a PermissionDescriptor and passing it to PermissionService.revokePermission. The following example revokes read privilege on MyACSObject 50 from Group 5:

import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PermissionDescriptor;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.OID;

OID acsObject = new OID("example.MyACSObject",
new BigDecimal(50));

OID party = new OID("com.arsdigita.kernel.Group", new BigDecimal(5));


PermissionDescriptor perm =
new PermissionDescriptor(PrivilegeDescriptor.READ,
acsObject, party);

PermissionService.revokePermission(perm);

The next example revokes admin privilege on all objects from User 100:

import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.UniversalPermissionDescriptor;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.OID;

OID party = new OID("com.arsdigita.kernel.User", new BigDecimal(100));

PermissionDescriptor perm =
new UniversalPermissionDescriptor(PrivilegeDescriptor.ADMIN,
party);

PermissionService.revokePermission(perm);

10.1.3. Basic Access Check

The basic access check indicate whether a user has a privilege on an object. User X has privilege Y on object Z if either of the following is true:

  • Privilege Y or admin has been granted universally to user X or some group to which X belongs.

  • Privilege Y or admin has been granted on object Z or some object from which Z inherits permissions (via Z's context) to user X or some group to which X belongs.

To perform this check, you create a PermissionDescriptor and pass it to PermissionService.checkPermission. The following example checks read privilege on MyACSObject 50 for User 100:

import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PermissionDescriptor;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.OID;

OID acsObject = new OID("example.MyACSObject",
new BigDecimal(50));

OID party = new OID("com.arsdigita.kernel.User", new BigDecimal(100));

PermissionDescriptor perm =
new PermissionDescriptor(PrivilegeDescriptor.READ,
acsObject, party);

if (PermissionService.checkPermission(perm)) {
// user 100 has read access on object 50
} else {
// user 100 does NOT have read access on object 50.
// You might handle this case by displaying an 
// "access forbidden" message.
}

As the previous examples have shown, operations performed on PermissionDescriptor can also be performed on UniversalPermissionDescriptor when dealing with universal access control (that is, access to all objects). The same applies for PermissionService.checkPermission(). The following example checks whether user 100 has admin privilege universally:

import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.UniversalPermissionDescriptor;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.OID;

OID party = new OID("com.arsdigita.kernel.User", new BigDecimal(100));


PermissionDescriptor perm =
new PermissionDescriptor(PrivilegeDescriptor.ADMIN,
party);

if (PermissionService.checkPermission(perm)) {
// user 100 has admin access universally (that is, on all objects).
} else {
// user 100 does not universal admin access universally.
// You might handle this case by displaying an 
// "access forbidden" message.
}

10.1.4. Allowed Targets Check

The allowed targets check is performed on a DomainCollection or DataCollection in order to filter the result set of domain/data objects to only those on which a given user has a given privilege. The rules for determining whether a given user has a given privilege on an object are described in Section 10.1.3 Basic Access Check.

You can be perform this filtering by using either PermissionService.filterObjects(DomainCollection, PrivilegeDescriptor, Party) or PermissionService.filterObjects(DataCollection, PrivilegeDescriptor, Party). The following example retrieves all MyACSObjects on which User 100 has read privilege:

import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PermissionDescriptor;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.OID;
import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.SessionManager;

DataCollection objects = SessionManager.getSession()
.retrieve("example.MyACSObject");

OID party = new OID("com.arsdigita.kernel.User", new BigDecimal(100));


PermissionService.filterObjects(object, PrivilegeDescriptor.READ, party);

// iterate over filtered results
while (objects.next()) {
...
}

10.1.5. Setting the Access Control Context of an ACSObject

An ACSObject can inherit permissions from another ACSObject, which is called its context. To set the context of an object, use PermissionService.setContext(object, context). The context may be set to null to signify that the object should not inherit permissions from any other object. Note that universal permissions still apply to any object, even if its context is null.

10.1.6. Defining New Privileges

There are 4 pre-defined privileges in the system, similar to file system privileges:

  • read - The privilege to read or view an object.

  • write - The privilege to write or edit an object.

  • create - The privilege to create new objects within an object. For example, a user who has create privilege on a given directory is allowed to create new files within the directory.

  • admin - Implies all other privileges.

Application developers may cautiously define new privileges to represent specific actions in the context of an application. For example, a content management system may support publishing a content item that is in final draft, but this operation should be restricted to certain parties for each content item. To accomplish this, the content management application creates a publish privilege from its initializer, as illustrated by the following code fragment.

if (PrivilegeDescriptor.get("publish") == null) {
PrivilegeDescriptor.createPrivilege("publish"); }