<?xml version="1.0"?>
<!--
  Copyright 2002-2004 The Apache Software Foundation or its licensors,
  as applicable.
  
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  
  http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
  <properties>
    <title>design usermgt</title>
  </properties>
  <body>
    <section name="Table of Contents">
      <macro name="toc">
        <param name="section" value="0"/>
        <param name="fromDepth" value="0"/>
        <param name="toDepth" value="4"/>
      </macro>
      <p>This document explains the requirements and the design of user management.</p>
    </section>
    <section name="Introduction">
      <p>
        User management provides the interfaces to manage users and groups.
      </p>
      <p>
        The current functionality is limited to administering users and groups. Self-registration of
        users is not (yet) implemented.
      </p>
    </section>
    <section name="Requirements">
      <ol>
        <li>It shall be possible to add, remove, and modify users </li>
        <li>It shall be possible to add, remove, and modify groups.</li>
        <li>The design shall guarantee that a users is always part of at least one group. </li>
      </ol>
      <subsection name="Non-functional requirements">
        <ol>
          <li>The design shall scale to thousands of users and groups.</li>
          <li>User management shall provide one service interface through which all changes
              are finally made. It shall be impossible to bypass this interface and make changes to
            the user administration in any other way.</li>
          <li>The design shall be extendible to an implementation of user management as a remote
            service.</li>
          <li>It must be possible to integrate user management with that of an application server
            (at least JBoss)</li>
        </ol>
      </subsection>
    </section>
    <section name="Design">
      <p>
        The design is centered around a simple domain model with users and groups and relations
        between them. In addition, there is one interface (facade) through which all changes to
        users and groups must be made. If a change is made to a user or group object, the change
        will only become visible after notifying user administration of the change through the
        interface. This approach also lends itself to an implementation where user administration is
        a remote service.  
      </p>
      <p>
        To avoid the creation of separate Data Transfer Objects for users and groups and to guarantee
        consistency through the user administration interface, the following approach is taken: 
      </p>
      <ul>
        <li>User and group objects have a package-scope constructor and must be created through the
          user administration interface</li>
        <li>Relations between users and groups can only be changed through the user administration
          interface. </li>
        <li>Users and groups may only be renamed through the user administration interface since a
          rename could violate constraints. </li>
        <li>User administration always returns copies of users and groups and does not allow direct
          manipulation of users and groups through their interface. Instead, user and group objects
          obtained through the user administration interface may be modified but after that user
          administration must be notified of the change. </li>
      </ul>
      <p>
        Integration with application server authentication is provided through persistent storage of
        the users and groups and their relations in a database. Based on this the integration in an
        application server can be configured. 
      </p>
    </section>
    <section name="Structure">
      <subsection name="Package Overview">
        <p>
          The design consists of two packages, a <code>usermgt</code> package with standard
          interfaces and implementations that are usable in any environment and a
          <code>usermgt.hibernate</code> package that provides specific implementations for
          persistence with hibernate. 
        </p>
        <img src="../umlpictures/class-diagram-org.wamblee.usermgt.packages.jpg" alt="Package overview."/>
      </subsection>
      <subsection name="Model">
        <p>
          The basic model is straightforward: a <code>User</code> can have relations with one or
          more <code>Group</code>s. Both objects implement <code>AbstractPersistent</code> to
          provide functionality for persistence. The <code>User</code> class guarantees that a user
          will always be part of at least one group. Both <code>User</code> and <code>Group</code>
          have package scope constructors and must be obtained through the user administration
          interface.  
        </p>
        <img src="../umlpictures/class-diagram-org.wamblee.usermgt.overview.jpg" alt="Basic model for users and groups."/>
      </subsection>
      <subsection name="Interface">
        <p>
          The interface of user administration is defined by (surprisingly)
          <code>UserAdministration</code>. The interface provides methods for creating, removing,
          renaming, and looking up users and groups. It also provides operations for managing the
          relations between users and groups and for notifying user administration of changes to a
          user or group. This is required since user administration returns copies of users and
          groups.  
        </p>
        <img src="../umlpictures/class-diagram-org.wamblee.usermgt.useradmin.jpg" alt="User administration interface."/>
        <p>
          A straightforward implementation of user administration is to create an implementation of
          the user administration and map this to a database using Hibernate. Nevertheless, this
          design would depend heavily on the behavior of Hibernate for lazy loading in combination
          with, possibly large, numbers of objects. Therefore, we provide a lower level
          implementation whereby the implementation of user administration delegates to a
          <code>UserSet</code> and <code>GroupSet</code> respectively. 
        </p>
        <p>
          It is then the responsibility of <code>UserAdministrationImpl</code> to manage the rules
          governing consistency of the user administration and the <code>UserSet</code> and
          <code>GroupSet</code> simply manage storage of the users and groups. 
        </p>
      </subsection>
      <subsection name="Persistence">
        <p>
          The <code>UserSet</code> and <code>GroupSet</code> interface both have an in-memory
          implementation and a Hibernate implementation. The Hibernate implementation is the one
          which will be used for actual deployments. The Hibernate implementation also uses caching
          at application level of users. This is done because user information is accessed
          frequently. Caching in
          Hibernate had a much lower performance (in tests it was 100 time slower) so that caching
          at application level is done instead. 
        </p>
        <img src="../umlpictures/class-diagram-org.wamblee.usermgt.usergroupset.jpg" alt="Persistence of users and groups."/>
      </subsection>
      <subsection name="Accessing the currently logged in user">
        <p>
          It is required to link together the security mechanism and user management to obtain
          a user object based on the currently logged in user. This functionality is defined by
          the <code>UserAccessor</code>. One implementation of this is the <code>JaasUserAccessor</code>
          which retrieves the user principal from JAAS (using the configured class of the user
          principal) and uses user administration to lookup the
          correct <code>User</code> object representing the user.
        </p>
        <img src="../umlpictures/class-diagram-org.wamblee.usermgt.useraccessor.jpg" alt="The user accessor."/>
      </subsection>
    </section>
    <section name="Dynamics">
      <p>
        A small number of sequence diagrams is used to illustrate how user management should be
        used and to describe the responsibilities of the involved objects. The sequence diagrams 
        do not cover the full functionality of user management. 
      </p>
      <subsection name="Adding a user">
        <p>
          To add a new user, first a group must be obtained from the user administration. This is
          because a user must always be part of at least one group.  
          After that, the user can be created with the basic properties of the user and with a
          reference to the group. The user administration then checks whether the user does not
          already exist and if so through a <code>UsermgtException</code>. Otherwise, the new user
          is created. 
        </p>
        <img src="../umlpictures/sequence-diagram-org.wamblee.usermgt.addinguser.jpg" alt="Adding a user."/>
      </subsection>
      <subsection name="Adding a user to a group">
        <p>
          To add a user to a group, the user and group must first be obtained from the user
          administration interface. After that, <code>addUserToGroup</code> is used to add the user
          to a group. Again, user administration checks that the user and group are valid before
          actually adding the user to the group. Since adding a user to a group modifies the user,
          the <code>UserSet</code> must be notified of this change by calling <code>userModified()</code>
          with the modified user. 
        </p>
        <img src="../umlpictures/sequence-diagram-org.wamblee.usermgt.addusertogroup.jpg" alt="Adding a user to a group."/>
      </subsection>
      <subsection name="Changing the password of a user">
        <p>
          To change the password of the user, the user must first be obtained from the user
          administration (not shown). Then, <code>changePassword()</code> must be called with both
          the old and new password as arguments. The password is then checked and if it is ok, the
          password is changed. Note that, for security reasons the interface of the user does not
          allow retrieval of the password. 
        </p>
        <img src="../umlpictures/sequence-diagram-org.wamblee.usermgt.changepassword.jpg" alt="Changing the password of a user. "/>
      </subsection>
    </section>
    <section name="Design Rules">
      <p>
        To use user management effectively, the following rules should be followed:
      </p>
      <ul>
        <li>After modifying a user or group, <code>userModified()</code> and
          <code>groupModified()</code> must be called on the user administration interface respectively. </li>
      </ul>
    </section>
  </body>
</document>
