Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Those tables are represented in Roller by the User and UserRole objects, which are POJOs stored by Roller's UserManager via Object Relational Mapping (ORM) technology (i.e. Apache OpenJPA).

Roller also does it's own authorization checks on user Roles. For each new user session, Roller creates a RollerSession object. RollerSession calls request.getUserPrincipal().getName() to get the user name, fetches corresponing User object from UserManager and holds on to that User object.

The RollerSession provides access to the session's authenticated user:

Code Block

public User getAuthenticatedUser()

The User object provides read/write access to user's roles:

Code Block

public boolean hasRole(String roleName)
public void grantRole(String roleName)
public Set getRoles()

As of Roller 4.0, Roller calls hasRole() for one reason, to ensure that only those with the admin role can:

  • View set the Admin options in the tabbed menu
  • Modify another user's profile
  • Edit any weblog
  • Set pinned field of a weblog entry
  • Use RAP web services

4.1.1 The problem with managing Users and Roles via ORM

For sites that have an external user repository or user permissions system, this is a problem. Some would like user information like email address, locale, timezone, fullname and etc. pulled from an external system. Some would like user's roles to be pulled from an external system. Some would like both.

...

Ensure that User objects are always retrieved via UserManager methods and never by ORM relationship management (e.g. never by weblog.getUser()). And, add any new required user profile fields directly to the User object.

Now, let's move from user profiles to user authentication.

...

Acegi is implemented as a Servlet Filter, which intercepts each request and decides if the user is authenticated, needs to login first, etc. Acegi takes care of routing the user to the login page and back to the original page that the user requested. Acegi wraps the ServletRequest so that it can return the
right value when request.getUserPrincipal() is called by the application.

4.2.1 The problem with relying solely on Acegi

Using Acegi makes Roller installation painless in standalone situations, but some Acegi skills are required to reconfigure Roller to authenticate against an LDAP system. Unfortunately, the only SSO system that Acegi supports out of the box is Yale CAS. Plus, some folks would like to disable Acegi to take advantage of the powerful auth & auth services that are built into containers now, e.g. SSO support that's built into Glassfish, Websphere, JBoss, etc.

...

Make it possible to turn off Acegi by modifying web.xml and to extend the Roller application class RollerContext to init without Acegi. Moving forward, we should not introduce further dependencies on Acegi in Roller.

4.

...

Roller also does it's own authorization checks on user Roles. For each new user session, Roller creates a RollerSession object. RollerSession calls request.getUserPrincipal().getName() to get the user name, fetches corresponing User object from UserManager and holds on to that User object.

The RollerSession provides access to the session's authenticated user:

Code Block

public User getAuthenticatedUser()

The User object provides read/write access to user's roles:

Code Block

public boolean hasRole(String roleName)
public void grantRole(String roleName)
public Set getRoles()

As of Roller 4.0, Roller calls hasRole() for one reason, to ensure that only those with the admin role can:

  • View set the Admin options in the tabbed menu
  • Modify another user's profile
  • Edit any weblog
  • Set pinned field of a weblog entry
  • Use RAP web services

4.4.1 The Problem

Because Roller uses the ORM system to load a User's Roles, the roles must come from the database. And because Roles are part of the User, some sort of join must happen to load each User object with Roles.

4.4.2 The Solution

Change Roller to rely on a single consistent permissions system rather than a mixture of Roles and WeblogPermissions. See below.

...

3 Roller manages user-weblog permissions

In addition to roles, which are global across a Roller site, Roller also manages each user's permissions to access weblogs. There is a many-to-many relationship between users and weblogs and it's stored in a database table:

...

Code Block
public boolean hasWritePermissions(User user)

4.

...

3.1 Problem

Permissions cannot be managed by external system because the User to Permissions to Weblog relationship is managed by the ORM, the information must be stored in Roller database tables and cannot be externalized and managed by another system.

4.

...

3.2 Solution

Remove Roller's dependence on UserRole and WeblogPermissions completely and put in place a single consistent permissions system.

...

5.3 Add new UserManager methods

First, we must provide a way for the Roller front-end to check permissionsany type of permission for a user.

Code Block
public boolean checkPermission(RollerPermission perm, User user);

Next, we need to provide a way for the Roller front-end to grant and revoke roles because roles imply global permssionspermissions.

Code Block
public void grantRole(String roleName, User user);
public void revokeRole(String roleName, User user);

The Roller UI front-end also needs to be able to grant and revoke weblog permissions:

Code Block
public void grantWeblogPermission(WeblogPermission perm, User user);
public void revokeWeblogPermission(WeblogPermssion perm, User user);

And finally, the front-end needs to be able to display the roles and permissions associated with each user:

Code Block
public GlobalPermssionList<String> getGlobalPermssiongetRoles(User user);
public List<WeblogPermission> getWeblogPermssions(User user);
public List<WeblogPermission> getWeblogPermssions(Weblog weblog);

5.4 Implemention of new UserManagement permissions methods

Global permissions are implied by role, so we'll keep the userrole table and UserRole POJO.

Weblog permissions will be stored in a new table called New roller_permisison table. This table should be fairly generic because someday we may want to permission other objects.

Code Block
create table roller_permission (
   id              varchar(48) not null primary key,
   username        varchar(255) not null,
   actions         varchar(255) not null, -- comma separated list of actions permitted by permission
   objectid        varchar(48),           -- for now this will always store weblogid
   objectType      varchar(255),          -- for now this will always be 'Weblog'
   datecreated     timestamp not null
)

...