How to Specify And Use Role Permissions

Draft 0.1
Dec 15, 2000
Ted Lee (tlee@startups.com)
 

1. Applicability

Read this document when all of the following are true:

If this document doesn't meet your needs, you may want to look at:

Background

The basic unified login model implements permission-based security, where users may be required to contain a particular role before being allowed access to a particular page.  However, there are some situations where this level of security may not be granular enough.  For instance, perhaps it would be desirable to allow users with an admin role to have different levels of admin permissions.  Under the basic unified login model, you would have to create a separate admin role for each permission, which would be cumbersome.

This document describes ways to customize the login process so that nearly any level of detail about a user or role may be used to determine access to a page.

2. Steps for Defining And Using Role Permissions

Basically, you want to override the isAccessibleTo() method defined in Model so that it checks whatever you need checked for access to the page.  This could be anything, but to be concrete we'll describe in this cookbook an example of adding some permissions to a role as a bunch of boolean flags.  You may choose to implement permissions in a different way, but the basic steps will be similar.

2.1 Define Permissions For The Role

Let's assume we have a role called ResourceLocatorAdminRole.  We want to add some permissions to the role, so that certain resource locator administrators have more privileges than others.  For the purposes of this example let's say that it is sufficient to add permissions as simple boolean bits (this could be done in much more sophisticated ways):

public class ResourceLocatorAdminRole extends UserRole {
    private boolean isAllowedToDeletePostings;
    private boolean isAllowedToCredit;
    private boolean isAllowedToModifyPermissions;
    ...

    public boolean isAllowedToDeletePostings() {
        return this.isAllowedToDeletePostings;
    }

    public void setAllowedToDeletePostings(boolean isAllowed) {
        this.isAllowedToDeletePostings = isAllowed;
    }

    // etc.
    ...
}

2.2 Override isAccessibleTo() in Model subclasses

Model contains a method which implements the basic unified login access permissions: The implementation of this method looks something like this:
public boolean isAccessibleTo(StartupsUser user)
    if (getRequiredRole() == null) {
        return true;
    }
    if (user == null) {
        return false;
    }
    return user.containsRole(getRequiredRole());
}
We want to override this method for Models representing pages that need to check the permissions we just defined in step 2.1.  For example:
public class AdminModifyPermissionsModel extends Model {
    public boolean isAccessibleTo(StartupsUser user) {
        if (super.isAccessibleTo(user)) {
            ResourceLocatorAdminRole theRole = (ResourceLocatorAdminRole)
                    user.getRole(ResourceLocatorAdminRole.class);
            return theRole.isAllowedToModifyPermissions();
        }
        return false;
    }

    public Class getRequiredRole() {
        return ResourceLocatorAdminRole.class;
    }

    public String getPermissionDeniedURL() {
        return "/resourcelocator/NotAllowedToModifyPermissions.jsp";
    }
}

The exact implementation of isAccessibleTo() depends on how the permissions are defined.

3.  Design Discussion

There are many ways to design an access control system.  Rather than overdesign up front, we've chosen to implement a solution that should work 80% of the time (using roles as access permission flags) while allowing for the possibility of making things more complex (via overriding isAccessibleTo()).  In the example we've purposely chosen to show a simple example, but it could easily be extended for a more hierarchical system.  But the point is that right now we don't have time to anticipate our needs exactly so we go with the simple thing that can be extended.

Known Problems

4 Version History

0.1 First Version