Adding to the stockpile of features that I've packed into seam-gen in recent months, I just committed a new seam-gen command that generates a front-end to Seam's identity management API (JBSEAM-3717). Identity management is one of the most significant additions to Seam in the Seam 2 code base. But since its just set of framework classes, you need something to tie it into your application to truly appreciate (or even give notice to) its potential.
With that in mind, I've introduced the new seam-gen command add-identity-management. This command weaves the components, views, and configurations of a front-end for managing users and roles using Seam's identity management API, adopted from the seamspace example, into an existing seam-gen project. By manage, I mean create, read, update, and delete (CRUD). While that may sound like it requires a lot of supplemental code, it really doesn't. The API not only provides data access components, it also includes Seam components that prep the data for the view and respond to UI events (i.e., UI controllers), glue code which you would otherwise have to write when creating these screens. The command also generates three JPA entity classes that bridge the API to your database, which I'll introduce shortly. But first, I want to encourage you to just try it.
You can put Seam's identity management to practice using seam-gen in three simple steps:
- Check out the Seam trunk from SVN and build it (or simply download Seam 2.1.2.GA when it's available)
- Seed a new project by invoking seam setup
- Generate the new project complete with identity management screens by invoking seam create-project add-identity-management
If you already have a seam-gen project started, and you haven't changed it too much (at least you haven't touched the <identity:security> component definition), you simply run seam add-identity-management from inside your project (use the full path to seam if it's not in your PATH environment variable). In either case, be sure to follow the post-operative instructions that get printed to the console, which are contingent on how your application is setup (in particular, your hibernate.hbm2ddl.auto setting).
So what do you get for your labor? Weeks worth of effort saved. On the next deployment of the application, you'll be able to manage users and roles, then be able to immediately turn around and login in using any one of the users you create. Here's a screenshot of the identity management launch page:
You can then check out the user management page, which lists each user, the roles the user is granted, and whether the user is enabled.
From the user management screen, you can add, edit, or delete a user. The add and edit operations take you to the user detail/editor page, shown here:
There are similar screens for managing the roles that can be assigned to a user. Here's the role management screen, which shows the roles and groups. A group is a role of a role, which is an easy way to assign the same roles to multiple users or to have role inheritance (e.g., a person in the admin role is also a member).
The role management page also supports the add, edit, and delete operations. Here's the detail/editor page for a role:
You'll notice that there is one user and three roles that are supplied out of the box. SQL statements that insert three common roles (admin, member and guest) and a user (admin, who is granted the admin role) into the database get appended to the project's resources/import-dev.sql script. You'll need to run these statements manually unless the database is set to be created by Hibernate's schema export tool when the application starts (i.e., hibernate.hbm2ddl.auto is create or create-drop).
What about security? That is the topic of the day after all. Well, you don't have to worry about locking down access, it's already covered. The identity management screens are secured by two built-in permissions, seam.user and seam.role, which are enforced by Seam's permission resolver. Both permissions are granted to users with the admin role by the following rule that gets appended to the project's security rules file, resources/security.drl, by seam-gen. This rule is consulted by Seam's rule-based permission resolver when any identity management CRUD operation is performed.
rule ManageAccount no-loop activation-group "permissions" when $perm: PermissionCheck(name == "seam.user" || == "seam.role", granted == false) Role(name == "admin") then $perm.grant(); end
You can customize this rule as needed, as well as the names of the role and even the admin user. Just use the identity management screens!
Of course, there's still some work you have to do to solder Seam's notion of a user account onto your domain model, but that's to be expected. Speaking of the user account, let's see how that gets mapped.
Seam provides a pluggable mechanism for defining an identity store. An identity store is what performs that data access for users and roles. Seam provides a JPA and an LDAP provider. We're going to focus on the JPA provider since that's what seam-gen sets up.
In the spirit of a declarative style of programming, you sprinkle identity-related annotations over a handful of properties on the JPA entity classes which you plan on using to map user accounts and roles to the database. These annotations, which are explained in detail in the reference documentation but are pretty self explanatory, are @UserPrincipal, @UserPassword, @UserEnabled, @UserRoles, @RoleName, @RoleGroups (and also @RoleConditional, which has special meaning). You then activate the JPA identity store in the Seam component descriptor and tell it which JPA entity class has the user annotations and which one the role annotations.
<security:jpa-identity-store user-class="com.domain.model.UserAccount" role-class="com.domain.model.UserRole"/>
Seam has parallel support for persistent permissions, which function as ACLs. Again, you have to instruct Seam as to which annotated JPA entity class will map a permission to the database using a component definition in the component descriptor:
At this point, you have to do the legwork for creating a front-end to manage persistence permissions since they are so closely tied to the business case. But at least the API is all setup and ready to employ. See the seamspace example in the Seam distribution for an example of persistence permissions, as well as how the identity management API is used as a whole. You should also check out the security chapter of the Seam reference documentation to learn about all the components in the identity and permissions management API and how they work.
In summary, here's what seam-gen adds to your project when you issue the command seam add-identity-management
- The /view/useradmin directory containing views for managing users and roles as well as images and a stylesheet to support them
- A link in the main menu bar to the identity management launch page
- UserAccount, UserRole, and UserPermission annotated JPA entity classes
- A blanket security rule for allowing the admin role to manage users and roles
- SQL statements for seeding the database with an admin user and a typical set of roles
- The component definitions that activate the JPA identity and permission stores
Now you have no excuse not to give Seam's identity management a try!
Credit goes to Shane Bryzak for developing the management screens and providing instructions for how to integrate them into a standalone application.
UPDATE: Thanks to Jason Porter, the add-identity-management command is available for ICEfaces projects in addition to RichFaces projects.