Changeset 8073

Show
Ignore:
Timestamp:
12/14/06 18:35:18 (3 years ago)
Author:
ogrisel
Message:

Heads up: directory / authentication refactoring (needed to plug LDAP support):
- add new API for directories (idField, passwordField, authenticate, ...)
- make the login and group names be the primary keys instead of incremented integer indexes
- get rid of useless roles directory

WARNING: you will need to delete your hypersonic data source at the next redeployment

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • ECMPlatform/NXDirectory/trunk/OSGI-INF/DirectoryTypes.xml

    r8000 r8073  
    22 
    33<component name="org.nuxeo.ecm.directory.types"> 
    4     <extension target="org.nuxeo.ecm.core.schema.TypeService" point="schema"> 
    5         <schema name="user" src="schema/user.xsd"/
    6         <schema name="group" src="schema/group.xsd"/> 
    7         <schema name="role" src="schema/role.xsd"/> 
    8         <schema name="user2group" src="schema/user2group.xsd"/> 
    9         <schema name="user2role" src="schema/user2role.xsd"/> 
    10         <schema name="group2group" src="schema/group2group.xsd"/> 
    11         <schema name="vocabulary" src="schema/vocabulary.xsd"/
     4  <extension target="org.nuxeo.ecm.core.schema.TypeService" 
     5    point="schema"
     6    <schema name="user" src="schema/user.xsd" /> 
     7    <schema name="group" src="schema/group.xsd" /> 
     8    <schema name="user2group" src="schema/user2group.xsd" /> 
     9    <schema name="group2group" src="schema/group2group.xsd" /> 
     10    <schema name="vocabulary" src="schema/vocabulary.xsd" /> 
     11  </extension
    1212 
    13     </extension> 
    14  
    15  
    16     <extension target="org.nuxeo.ecm.core.schema.TypeService" point="doctype"> 
    17         <doctype name="User" extends="Document"> 
    18             <schema name="user"/> 
    19         </doctype> 
    20         <doctype name="Group" extends="Document"> 
    21             <schema name="group"/> 
    22         </doctype> 
    23         <doctype name="Role" extends="Document"> 
    24             <schema name="role"/> 
    25         </doctype> 
    26         <doctype name="User2Group" extends="Document"> 
    27             <schema name="user2group"/> 
    28         </doctype> 
    29         <doctype name="User2Role" extends="Document"> 
    30             <schema name="user2role"/> 
    31         </doctype> 
    32         <doctype name="Group2Group" extends="Document"> 
    33             <schema name="group2group"/> 
    34         </doctype> 
    35         <doctype name="Vocabulary" extends="Document"> 
    36             <schema name="vocabulary"/> 
    37         </doctype> 
    38     </extension> 
    39  
     13  <extension target="org.nuxeo.ecm.core.schema.TypeService" 
     14    point="doctype"> 
     15    <doctype name="User" extends="Document"> 
     16      <schema name="user" /> 
     17    </doctype> 
     18    <doctype name="Group" extends="Document"> 
     19      <schema name="group" /> 
     20    </doctype> 
     21    <doctype name="User2Group" extends="Document"> 
     22      <schema name="user2group" /> 
     23    </doctype> 
     24    <doctype name="Group2Group" extends="Document"> 
     25      <schema name="group2group" /> 
     26    </doctype> 
     27    <doctype name="Vocabulary" extends="Document"> 
     28      <schema name="vocabulary" /> 
     29    </doctype> 
     30  </extension> 
    4031</component> 
  • ECMPlatform/NXDirectory/trunk/resources/schema/group.xsd

    r5876 r8073  
    66        > 
    77 
    8         <xs:element name="id" type="xs:integer"/> 
    9         <xs:element name="xgroup" type="xs:string"/> 
     8        <xs:element name="groupname" type="xs:string"/> 
     9    <xs:element name="description" type="xs:string"/> 
     10   
    1011 
    1112</xs:schema> 
  • ECMPlatform/NXDirectory/trunk/resources/schema/group2group.xsd

    r5876 r8073  
    88         
    99        <xs:element name="id" type="xs:integer"/> 
    10         <xs:element name="parentGroupId" type="xs:integer"/> 
    11         <xs:element name="childGroupId" type="xs:integer"/> 
     10        <xs:element name="parentGroupId" type="xs:string"/> 
     11        <xs:element name="childGroupId" type="xs:string"/> 
    1212 
    1313</xs:schema> 
  • ECMPlatform/NXDirectory/trunk/resources/schema/user.xsd

    r6164 r8073  
    66        > 
    77         
    8          
    9         <xs:element name="id" type="xs:integer"/> 
    10         <xs:element name="user" type="xs:string"/> 
     8        <xs:element name="username" type="xs:string"/> 
    119        <xs:element name="password" type="xs:string"/> 
    1210        <xs:element name="firstName" type="xs:string"/> 
  • ECMPlatform/NXDirectory/trunk/resources/schema/user2group.xsd

    r5876 r8073  
    88         
    99        <xs:element name="id" type="xs:integer"/> 
    10         <xs:element name="userId" type="xs:integer"/> 
    11         <xs:element name="groupId" type="xs:integer"/> 
     10        <xs:element name="userId" type="xs:string"/> 
     11        <xs:element name="groupId" type="xs:string"/> 
    1212 
    1313</xs:schema> 
  • ECMPlatform/NXDirectory/trunk/src/org/nuxeo/ecm/directory/Session.java

    r7824 r8073  
    2222import org.nuxeo.ecm.core.api.DocumentModelList; 
    2323 
    24  
    2524/** 
    2625 * A session used to access entries in a directory. 
    2726 * <p> 
    28  * This class is used to create, obtain, modify and delete entries in a directory. 
    29  * @see @see org.nuxeo.ecm.directory.Directory#getSession() 
     27 * This class is used to create, obtain, modify and delete entries in a 
     28 * directory. 
     29 *  
     30 * @see 
     31 * @see org.nuxeo.ecm.directory.Directory#getSession() 
    3032 * @author glefter@nuxeo.com 
    3133 */ 
     
    3335public interface Session { 
    3436 
    35         public Directory getDirectory(); 
    36      
    37         /** 
    38          * Retrieves a directory entry using its id. 
    39          * <p> 
    40          * TODO what happens when the entry is not found?  
    41          * return null if not found? 
    42          *  
    43          * @param id the entry id 
    44          * @return a DocumentModel representing the entry 
    45          * @throws DirectoryException 
    46          */ 
    47         public DocumentModel getEntry(String id) throws DirectoryException; 
    48          
    49         /** 
    50          * Retrieves all the entries in the directory. 
    51          *  
    52          * @return a collection with all the entries in the directory 
    53          * @throws DirectoryException 
    54          */ 
    55         public DocumentModelList getEntries() throws DirectoryException; 
    56                  
    57         /** 
    58          * Creates an entry in a directory. 
    59          *  
    60          * @param map A map with keys and values that should be stored in a directory 
    61          * <p> 
    62          * Note: The values in the map should be of type String 
    63          * @return The new entry created in the directory 
    64          * @throws UnsupportedOperationException if the directory does not allow the creation of new entries 
    65          * @throws DirectoryException if a communication exception occurs 
    66          */ 
    67          
    68         public DocumentModel createEntry(Map<String, Object> map) throws UnsupportedOperationException, DirectoryException; 
    69          
    70     /** 
    71          * Updates a directory entry. 
    72          *  
    73          * @param docModel The entry to update 
    74          * @throws UnsupportedOperationException if the directory does not support entry updating 
    75          * @throws DirectoryException if a communication error occurs 
    76          */ 
    77         public void updateEntry(DocumentModel docModel) throws UnsupportedOperationException, DirectoryException; 
     37    public Directory getDirectory(); 
     38 
     39    /** 
     40     * Retrieves a directory entry using its id. 
     41     * <p> 
     42     * TODO what happens when the entry is not found? return null if not found? 
     43     *  
     44     * @param id 
     45     *            the entry id 
     46     * @return a DocumentModel representing the entry 
     47     * @throws DirectoryException 
     48     */ 
     49    public DocumentModel getEntry(String id) throws DirectoryException; 
     50 
     51    /** 
     52     * Retrieves all the entries in the directory. 
     53     *  
     54     * @return a collection with all the entries in the directory 
     55     * @throws DirectoryException 
     56     */ 
     57    public DocumentModelList getEntries() throws DirectoryException; 
     58 
     59    /** 
     60     * Creates an entry in a directory. 
     61     *  
     62     * @param map 
     63     *            A map with keys and values that should be stored in a 
     64     *            directory 
     65     *            <p> 
     66     *            Note: The values in the map should be of type String 
     67     * @return The new entry created in the directory 
     68     * @throws UnsupportedOperationException 
     69     *             if the directory does not allow the creation of new entries 
     70     * @throws DirectoryException 
     71     *             if a communication exception occurs 
     72     */ 
     73 
     74    public DocumentModel createEntry(Map<String, Object> map) 
     75            throws UnsupportedOperationException, DirectoryException; 
     76 
     77    /** 
     78     * Updates a directory entry. 
     79     *  
     80     * @param docModel 
     81     *            The entry to update 
     82     * @throws UnsupportedOperationException 
     83     *             if the directory does not support entry updating 
     84     * @throws DirectoryException 
     85     *             if a communication error occurs 
     86     */ 
     87    public void updateEntry(DocumentModel docModel) 
     88            throws UnsupportedOperationException, DirectoryException; 
    7889 
    7990    /** 
    8091     * Deletes a directory entry. 
    8192     *  
    82      * @param docModel The entry to delete 
    83      * @throws UnsupportedOperationException if the directory does not support entry deleting 
    84      * @throws DirectoryException if a communication error occurs 
    85      */ 
    86     public void deleteEntry(DocumentModel docModel) throws UnsupportedOperationException, DirectoryException; 
    87      
     93     * @param docModel 
     94     *            The entry to delete 
     95     * @throws UnsupportedOperationException 
     96     *             if the directory does not support entry deleting 
     97     * @throws DirectoryException 
     98     *             if a communication error occurs 
     99     */ 
     100    public void deleteEntry(DocumentModel docModel) 
     101            throws UnsupportedOperationException, DirectoryException; 
     102 
    88103    /** 
    89104     * Deletes a directory entry by id 
    90105     *  
    91      * @param id The id of the entry to delete 
    92      * @throws UnsupportedOperationException if the directory does not support entry deleting 
    93      * @throws DirectoryException if a communication error occurs 
    94      */ 
    95     public void deleteEntry(String id) throws UnsupportedOperationException, DirectoryException; 
    96      
    97         /* FIXME: 
    98          * Parses a query string and create a query object for this directory. 
    99          *   
    100          * @param query the query string to parse 
    101          * @return a new query object 
    102          * @throws QueryException if the query cannot be parsed 
    103          
    104         * maybe not needed 
    105     * public SQLQuery createQuery(String query) throws QueryException; 
    106         */ 
    107      
    108         /** 
    109          * Executes a simple query. The conditions will be 'AND'-ed. '*' can be used 
    110      * as a wildcard. 
    111      * TODO: make this API perform an exact match; refactor the wildcard match to another function  
    112      * that will also support other operations, e.g. OR, NOT, etc. 
     106     * @param id 
     107     *            The id of the entry to delete 
     108     * @throws UnsupportedOperationException 
     109     *             if the directory does not support entry deleting 
     110     * @throws DirectoryException 
     111     *             if a communication error occurs 
     112     */ 
     113    public void deleteEntry(String id) throws UnsupportedOperationException, 
     114            DirectoryException; 
     115 
     116    /* 
     117     * FIXME: Parses a query string and create a query object for this 
     118     * directory. 
     119     *  
     120     * @param query the query string to parse @return a new query object @throws 
     121     * QueryException if the query cannot be parsed 
     122     *  
     123     * maybe not needed public SQLQuery createQuery(String query) throws 
     124     * QueryException; 
     125     */ 
     126 
     127    /** 
     128     * Executes a simple query. The conditions will be 'AND'-ed. '*' can be used 
     129     * as a wildcard. TODO: make this API perform an exact match; refactor the 
     130     * wildcard match to another function that will also support other 
     131     * operations, e.g. OR, NOT, etc. 
    113132     *  
    114133     * Note: the LDAPSession implementation already does exact match 
    115          *  
    116          * @param filter a filter to apply to entries in directory 
    117          * @return a list of document models containing the entries matched by the query 
    118          * @throws DirectoryException if a communication error occurs 
    119          */ 
    120         public DocumentModelList query(Map<String, Object> filter) throws DirectoryException; 
    121          
     134     *  
     135     * @param filter 
     136     *            a filter to apply to entries in directory 
     137     * @return a list of document models containing the entries matched by the 
     138     *         query 
     139     * @throws DirectoryException 
     140     *             if a communication error occurs 
     141     */ 
     142    public DocumentModelList query(Map<String, Object> filter) 
     143            throws DirectoryException; 
     144 
    122145    /** 
    123146     * Executes a simple query. The conditions will be 'AND'-ed. 
     
    125148     * fieldNames present in the fulltext set are treated as a fulltext match 
    126149     *  
    127      * @param filter a filter to apply to entries in directory 
    128      * @param fulltext a set of field that should be treated as a fulltext search 
    129      * @return a list of document models containing the entries matched by the query 
    130      * @throws DirectoryException if a communication error occurs 
     150     * @param filter 
     151     *            a filter to apply to entries in directory 
     152     * @param fulltext 
     153     *            a set of field that should be treated as a fulltext search 
     154     * @return a list of document models containing the entries matched by the 
     155     *         query 
     156     * @throws DirectoryException 
     157     *             if a communication error occurs 
    131158     */ 
    132159    public DocumentModelList query(Map<String, Object> filter, 
    133160            Set<String> fulltext) throws DirectoryException; 
     161 
     162    // TODO: create an API to allow sql AND/OR/NOT/LIKE conditions 
     163    // public DocumentModelList query(Criteria criteria ) throws 
     164    // DirectoryException; 
     165 
     166    /** 
     167     * Commits any changes on this session. 
     168     *  
     169     * @throws UnsupportedOperationException 
     170     *             if the directory does not support transactions 
     171     * @throws DirectoryException 
     172     *             if a communication error occurs 
     173     *             <p> 
     174     *             In this case the session will be automatically rollbacked 
     175     */ 
     176    public void commit() throws UnsupportedOperationException, 
     177            DirectoryException; 
     178 
     179    /** 
     180     * Rollbacks any changes on this session. 
     181     *  
     182     * @throws UnsupportedOperationException 
     183     *             if the associated directory does not support transactions 
     184     * @throws DirectoryException 
     185     *             if a communication error occurs 
     186     *             <p> 
     187     *             In this case, the session will be automatically rollbacked 
     188     *             anyway 
     189     */ 
     190    public void rollback() throws UnsupportedOperationException, 
     191            DirectoryException; 
     192 
     193    /** 
     194     * Closes the session and all open result sets obtained from this session. 
     195     * <p> 
     196     * Releases this Connection object's resources immediately instead of 
     197     * waiting for them to be automatically released. 
     198     * <p> 
     199     * TODO: should this operation auto-commit pending changes? 
     200     *  
     201     * @throws DirectoryException 
     202     *             if a communication error occurs 
     203     */ 
     204    public void close() throws DirectoryException; 
     205 
     206    /** 
     207     * Execute a query using filter and return only the column <b>columnName</b> 
     208     *  
     209     * @param filter 
     210     *            the filter for the query 
     211     * @param columnName 
     212     *            the column whose content should be returned 
     213     * @return the list with the values of <b>columnName</b> for the entries 
     214     *         matching <b>filter</b> 
     215     * @throws DirectoryException 
     216     */ 
     217    public List<String> getProjection(Map<String, Object> filter, 
     218            String columnName) throws DirectoryException; 
     219 
     220    /** 
     221     * Execute a query using filter and return only the column <b>columnName</b> 
     222     *  
     223     * @param filter 
     224     *            the filter for the query 
     225     * @param columnName 
     226     *            the column whose content should be returned 
     227     * @return the list with the values of <b>columnName</b> for the entries 
     228     *         matching <b>filter</b> 
     229     * @throws DirectoryException 
     230     */ 
     231    public String getUniqueProjection(Map<String, Object> filter, 
     232            String columnName) throws DirectoryException; 
     233 
     234    public List<String> getProjection(String columnName) 
     235            throws DirectoryException; 
     236 
     237    /** 
     238     * Tell whether the directory implementation can be used as an 
     239     * authenticating backend for the UserManager (based on login / password 
     240     * check) 
     241     *  
     242     * @return true is the directory is authentication aware 
     243     * @throws DirectoryException 
     244     */ 
     245    public boolean isAuthenticating() throws DirectoryException; 
     246 
     247    /** 
     248     * Check that the credentials provided by the UserManager match those 
     249     * registered in the directory. If username is not in the directory, 
     250     * this should return false instead of throrwing an exception. 
     251     *  
     252     * @param username 
     253     * @param password 
     254     * @return true is the credentials match those stored in the directory 
     255     */ 
     256    public boolean authenticate(String login, String password) 
     257            throws DirectoryException; 
    134258     
    135     // TODO: create an API to allow sql AND/OR/NOT/LIKE conditions 
    136     //public DocumentModelList query(Criteria criteria ) throws DirectoryException; 
     259    /** 
     260     * The Id field is the name of the field that is used a primary key: 
     261     * unique and not null value in the whole directory. This field is also 
     262     * used as login field if the directory is authenticating. 
     263     *  
     264     * @return the name of the id field 
     265     */ 
     266    public String getIdField(); 
    137267     
    138      
    139         /** 
    140          * Commits any changes on this session. 
    141          *  
    142          * @throws UnsupportedOperationException if the directory does not support transactions 
    143          * @throws DirectoryException if a communication error occurs 
    144          * <p> 
    145          * In this case the session will be automatically rollbacked 
    146          */ 
    147         public void commit() throws UnsupportedOperationException, DirectoryException; 
    148          
    149         /** 
    150          * Rollbacks any changes on this session. 
    151          *  
    152          * @throws UnsupportedOperationException if the associated directory does not support transactions 
    153          * @throws DirectoryException if a communication error occurs 
    154          * <p> 
    155          * In this case, the session will be automatically rollbacked anyway 
    156          */ 
    157         public void rollback() throws UnsupportedOperationException, DirectoryException; 
    158          
    159         /** 
    160          * Closes the session and all open result sets obtained from this session. 
    161          * <p> 
    162          * Releases this Connection object's resources immediately instead of 
    163          * waiting for them to be automatically released. 
    164          * <p> 
    165          * TODO: should this operation auto-commit pending changes? 
    166          * @throws DirectoryException if a communication error occurs 
    167          */ 
    168         public void close() throws DirectoryException; 
    169      
    170     /** 
    171      * Execute a query using filter and return only the column <b>columnName</b> 
    172      * @param filter the filter for the query 
    173      * @param columnName the column whose content should be returned 
    174      * @return the list with the values of <b>columnName</b> for the entries matching <b>filter</b> 
    175      * @throws DirectoryException 
    176      */ 
    177     public List<String> getProjection(Map<String, Object> filter, String columnName) throws DirectoryException; 
    178  
    179     /** 
    180      * Execute a query using filter and return only the column <b>columnName</b> 
    181      * @param filter the filter for the query 
    182      * @param columnName the column whose content should be returned 
    183      * @return the list with the values of <b>columnName</b> for the entries matching <b>filter</b> 
    184      * @throws DirectoryException 
    185      */ 
    186     public String getUniqueProjection(Map<String, Object> filter, String columnName) throws DirectoryException; 
    187  
    188     public List<String> getProjection(String columnName) throws DirectoryException; 
    189      
     268    /** 
     269     * @return the nam,e of the field to store the password if the directory is 
     270     * authenticating (can be null) 
     271     */ 
     272    public String getPasswordField(); 
     273 
    190274} 
  • ECMPlatform/NXDirectory/trunk/src/org/nuxeo/ecm/directory/api/AbstractDirectoryClient.java

    r7824 r8073  
    2828 * @author Bogdan Stefanescu 
    2929 *  
     30 * XXX: Aren't we leaking sessions here? All those sessions should be 
     31 * enclosed in try/finally blocks 
    3032 */ 
    3133public abstract class AbstractDirectoryClient implements DirectoryClient { 
     
    128130        return getSession().getDirectory(); 
    129131    } 
     132     
     133    public boolean isAuthenticating() throws DirectoryException { 
     134        return getSession().isAuthenticating(); 
     135    } 
     136     
     137    public boolean authenticate(String username, String password) 
     138        throws DirectoryException { 
     139        return getSession().authenticate(username, password); 
     140    } 
     141     
     142    public String getIdField() { 
     143        return getSession().getIdField(); 
     144    } 
     145     
     146    public String getPasswordField() { 
     147        return getSession().getPasswordField(); 
     148    } 
    130149 
    131150} 
  • ECMPlatform/NXDirectory/trunk/src/org/nuxeo/ecm/directory/constants/GroupDirectory.java

    r5857 r8073  
    2121public class GroupDirectory { 
    2222    public static final String DIRECTORY_NAME = "groupDirectory"; 
    23     public static final String ID_COLUMN = "id"; 
    24     public static final String GROUP_COLUMN = "xgroup"; 
     23    public static final String GROUP_COLUMN = "groupname"; 
    2524} 
  • ECMPlatform/NXDirectory/trunk/src/org/nuxeo/ecm/directory/constants/UserDirectory.java

    r6164 r8073  
    2020 */ 
    2121public class UserDirectory { 
     22    // this should be moved to an extension point 
    2223    public static final String DIRECTORY_NAME = "userDirectory"; 
    23     public static final String USER_COLUMN = "user"; 
    24     public static final String ID_COLUMN = "id"; 
    2524    public static final String FIRSTNAME_COLUMN = "firstName"; 
    2625    public static final String LASTNAME_COLUMN = "lastName"; 
    2726    public static final String COMPANY_COLUMN = "company"; 
    28     public static final String PASSWORD_COLUMN = "password"; 
    2927} 
  • ECMPlatform/NXSQLDirectory/trunk/build.xml

    r6915 r8073  
    108108        <target name="deploy" depends="build" description="Deploy the JAR archive"> 
    109109                <copy todir="${jboss.home}/server/${jboss.config}/deploy" file="dist/${ant.project.name}.jar"/> 
    110                 <copy overwrite="true" todir="${jboss.home}/server/${jboss.config}/deploy" file="${basedir}/resources/CoreDirectories-bundle.xml"/> 
     110                <copy overwrite="true" todir="${jboss.home}/server/${jboss.config}/deploy" file="${basedir}/resources/default-sql-directories-bundle.xml"/> 
    111111        </target> 
    112112 
    113113        <target name="deploy-ecm" depends="build" description="Deploy the JAR archive"> 
    114114                <copy todir="${jboss.home}/server/${jboss.config}/deploy/${nuxeo.ear}" file="dist/${ant.project.name}.jar"/> 
    115                 <copy overwrite="true" todir="${jboss.home}/server/${jboss.config}/deploy/${nuxeo.ear}" file="${basedir}/resources/CoreDirectories-bundle.xml"/> 
     115                <copy overwrite="true" todir="${jboss.home}/server/${jboss.config}/deploy/${nuxeo.ear}" file="${basedir}/resources/default-sql-directories-bundle.xml"/> 
    116116        </target> 
    117117 
  • ECMPlatform/NXSQLDirectory/trunk/resources/setup-hsqldb.sql

    r7684 r8073  
    11DROP TABLE users IF EXISTS; 
    22CREATE TABLE users ( 
    3   id integer NOT NULL, 
    4   user char(200), 
     3  username char(200), 
    54  password char(200), 
    65  firstName char(200),  
    76  lastName char(200),  
    87  company char(200), 
     8  PRIMARY KEY(username) 
     9); 
     10 
     11INSERT INTO users(username, password) VALUES ('Administrator', 'Administrator'); 
     12 
     13DROP TABLE groups IF EXISTS; 
     14CREATE TABLE groups ( 
     15  groupname varchar(200), 
     16  description varchar(500), 
     17  PRIMARY KEY(groupname) 
     18); 
     19 
     20INSERT INTO groups VALUES('members', ''); 
     21INSERT INTO groups VALUES('administrators', ''); 
     22 
     23DROP TABLE user2group IF EXISTS; 
     24CREATE TABLE user2group ( 
     25  id integer,  
     26  userId varchar(200) NOT NULL, 
     27  groupId varchar(200) NOT NULL, 
    928  PRIMARY KEY(id) 
    1029); 
    1130 
    12 INSERT INTO users(id, user, password) VALUES (1, 'Administrator', 'Administrator'); 
    13  
    14 DROP TABLE roles IF EXISTS; 
    15 CREATE TABLE roles ( 
    16   id integer NOT NULL, 
    17   role varchar(200), 
    18   PRIMARY KEY (id) 
    19 ); 
    20  
    21 INSERT INTO roles values(1, 'regular'); 
    22 INSERT INTO roles values(2, 'admin'); 
    23  
    24  
    25 DROP TABLE user2role IF EXISTS; 
    26 CREATE TABLE user2role ( 
    27   id integer NOT NULL,  
    28   userId integer NOT NULL,  
    29   roleId integer NOT NULL,  
    30   PRIMARY KEY (id) 
    31 ); 
    32  
    33 INSERT INTO user2role VALUES (1,1,1); 
    34 INSERT INTO user2role VALUES (2,1,2); 
    35  
    36 DROP TABLE groups IF EXISTS; 
    37 CREATE TABLE groups ( 
    38   id integer NOT NULL, 
    39   xgroup char(200), 
    40   PRIMARY KEY(id) 
    41 ); 
    42  
    43 INSERT INTO groups VALUES(1, 'members'); 
    44 INSERT INTO groups VALUES(2, 'administrators'); 
    45  
    46 DROP TABLE user2group IF EXISTS; 
    47 CREATE TABLE user2group ( 
    48   id integer NOT NULL,  
    49   userId integer NOT NULL, 
    50   groupId integer NOT NULL, 
    51   PRIMARY KEY(id) 
    52 ); 
    53  
    54 INSERT INTO user2group VALUES(1, 1, 1); 
    55 INSERT INTO user2group VALUES(2, 1, 2); 
     31INSERT INTO user2group VALUES(1, 'Administrator', 'members'); 
     32INSERT INTO user2group VALUES(2, 'Administrator', 'administrators'); 
    5633 
    5734DROP TABLE group2group IF EXISTS; 
    5835CREATE TABLE group2group ( 
    5936  id integer NOT NULL,  
    60   parentGroupId integer NOT NULL,  
    61   childGroupId integer NOT NULL,  
     37  parentGroupId varchar(200) NOT NULL,  
     38  childGroupId varchar(200) NOT NULL,  
    6239  PRIMARY KEY(id) 
    6340); 
  • ECMPlatform/NXSQLDirectory/trunk/src/org/nuxeo/ecm/directory/sql/SQLDirectory.java

    r7683 r8073  
    3838public class SQLDirectory implements Directory { 
    3939    private static final Log log = LogFactory.getLog(SQLDirectory.class); 
     40 
    4041    private DataSource dataSource; 
     42 
    4143    private SimpleIdGenerator idGenerator; 
     44 
    4245    SQLDirectoryDescriptor config; 
     46 
    4347    private List<Session> sessions = new ArrayList<Session>(); 
     48 
    4449    boolean managedSQLSession; 
    4550 
    46     public SQLDirectory(SQLDirectoryDescriptor config) throws DirectoryException { 
     51    public SQLDirectory(SQLDirectoryDescriptor config) 
     52            throws DirectoryException { 
    4753        this.config = config; 
    4854        setupTables(); 
     
    5056        try { 
    5157            sqlConnection = getConnection(); 
    52             if(config.autoincrementIdColumn) { 
    53                 this.idGenerator = new SimpleIdGenerator(sqlConnection, config.getTableName(), config.getIdColumn()); 
     58            if (config.autoincrementIdField) { 
     59                this.idGenerator = new SimpleIdGenerator(sqlConnection, config 
     60                        .getTableName(), config.getIdField()); 
    5461            } 
    5562        } finally { 
    56             try { sqlConnection.close(); } catch(Exception e) {} 
    57         } 
    58     } 
    59  
     63            try { 
     64                sqlConnection.close(); 
     65            } catch (Exception e) { 
     66            } 
     67        } 
     68    } 
    6069 
    6170    private void setupTables() throws DirectoryException { 
    6271        String sqlScript = config.sqlScript; 
    63         if(sqlScript==null) { 
     72        if (sqlScript == null) { 
    6473            return; 
    6574        } 
     
    7281            sqlConnection = getConnection(); 
    7382            Statement stmt = sqlConnection.createStatement(); 
    74             rs = stmt.executeQuery("select * from users where id=1"); 
    75         } catch(SQLException e) { 
     83            rs = stmt.executeQuery("select * from users where username=user_1"); 
     84        } catch (SQLException e) { 
    7685            simpleTableTest = false; 
    7786        } finally { 
    78             try { rs.close(); } catch(Exception e2) {} 
    79             try { sqlConnection.close(); } catch(Exception e2) {} 
    80         } 
    81  
    82  
    83         if(simpleTableTest && !config.forceExecuteScript) { 
    84             log.info("NOT executing sql script (simpleTableTest succeeded and forceExecuteScript is not set"); 
     87            try { 
     88                rs.close(); 
     89            } catch (Exception e2) { 
     90            } 
     91            try { 
     92                sqlConnection.close(); 
     93            } catch (Exception e2) { 
     94            } 
     95        } 
     96 
     97        if (simpleTableTest && !config.forceExecuteScript) { 
     98            log 
     99                    .info("NOT executing sql script (simpleTableTest succeeded and forceExecuteScript is not set"); 
    85100            return; 
    86101        } 
     
    89104        BufferedReader reader = null; 
    90105        try { 
    91             InputStream is = this.getClass().getClassLoader().getResourceAsStream(sqlScript); 
    92             if(is==null) { 
    93                 throw new DirectoryException("SQL Script not found: " + sqlScript); 
     106            InputStream is = this.getClass().getClassLoader() 
     107                    .getResourceAsStream(sqlScript); 
     108            if (is == null) { 
     109                throw new DirectoryException("SQL Script not found: " 
     110                        + sqlScript); 
    94111            } 
    95112 
     
    98115            String line; 
    99116 
    100             while( (line = reader.readLine()) != null) { 
     117            while ((line = reader.readLine()) != null) { 
    101118                buffer.append(line).append("\n"); 
    102119            } 
     
    110127            stmt.execute(buffer.toString()); 
    111128 
    112         } catch(SQLException e) { 
     129        } catch (SQLException e) { 
    113130            throw new DirectoryException("Directory initialization failed.", e); 
    114         } catch(IOException e) { 
    115             throw new DirectoryException("Read error while reading SQL Script.", e); 
     131        } catch (IOException e) { 
     132            throw new DirectoryException( 
     133                    "Read error while reading SQL Script.", e); 
    116134        } finally { 
    117             try { sqlConnection.close(); } catch(Exception e) {} 
    118             try { reader.close(); } catch(Exception e) {} 
    119         } 
    120  
    121  
    122  
    123     } 
    124  
     135            try { 
     136                sqlConnection.close(); 
     137            } catch (Exception e) { 
     138            } 
     139            try { 
     140                reader.close(); 
     141            } catch (Exception e) { 
     142            } 
     143        } 
     144    } 
    125145 
    126146    private void lookupDataSource() throws DirectoryException { 
    127147        try { 
    128             if(config.dataSourceName!=null) { 
     148            if (config.dataSourceName != null) { 
    129149                managedSQLSession = true; 
    130150                InitialContext context = new InitialContext(); 
    131                 this.dataSource = (DataSource) context.lookup(config.dataSourceName); 
     151                this.dataSource = (DataSource) context 
     152                        .lookup(config.dataSourceName); 
    132153            } else { 
    133154                managedSQLSession = false; 
    134                 dataSource = new SimpleDataSource(config.dbUrl, config.dbDriver, config.dbUser, config.dbPassword); 
     155                dataSource = new SimpleDataSource(config.dbUrl, 
     156                        config.dbDriver, config.dbUser, config.dbPassword); 
    135157            } 
    136158            log.info("found datasource: " + dataSource); 
    137         } catch(Exception e) { 
     159        } catch (Exception e) { 
    138160            log.error("dataSource lookup failed", e); 
    139161            throw new DirectoryException("dataSource lookup failed", e); 
     
    143165    private Connection getConnection() throws DirectoryException { 
    144166        try { 
    145             if(dataSource == null) { 
     167            if (dataSource == null) { 
    146168                lookupDataSource(); 
    147169            } 
    148170            return dataSource.getConnection(); 
    149         } catch(SQLException e) { 
     171        } catch (SQLException e) { 
    150172            throw new DirectoryException("could not obtain a connection", e); 
    151173        } 
     
    166188    public Session getSession() throws DirectoryException { 
    167189        Connection sqlConnection = getConnection(); 
    168         Session session = new SQLSession( 
    169                 this, 
    170                 config, 
    171                 sqlConnection, 
    172                 idGenerator, 
    173                 managedSQLSession 
    174         ); 
     190        Session session = new SQLSession(this, config, sqlConnection, 
     191                idGenerator, managedSQLSession); 
    175192        sessions.add(session); 
    176193        return session; 
    177194    } 
     195 
    178196    void removeSession(Session session) { 
    179197        sessions.remove(session); 
     
    182200    public void shutdown() { 
    183201        try { 
    184             for(Session session: sessions) { 
     202            for (Session session : sessions) { 
    185203                session.close(); 
    186204            } 
    187205            sessions = null; 
    188         } catch(DirectoryException e) { 
     206        } catch (DirectoryException e) { 
    189207            log.error("exception during shutdown", e); 
    190208        } 
  • ECMPlatform/NXSQLDirectory/trunk/src/org/nuxeo/ecm/directory/sql/SQLDirectoryDescriptor.java

    r7683 r8073  
    4545    public String tableName; 
    4646 
    47     @XNode("idColumn") 
    48     public String idColumn
     47    @XNode("idField") 
     48    public String idField
    4949 
    5050    @XNode("sqlScript") 
     
    5454    public boolean forceExecuteScript; 
    5555 
    56     @XNode("autoincrementIdColumn") 
    57     public boolean autoincrementIdColumn
     56    @XNode("autoincrementIdField") 
     57    public boolean autoincrementIdField
    5858 
     59    @XNode("passwordField") 
     60    private String passwordField; 
    5961 
    6062    public String getDataSourceName() { 
     
    6466        this.dataSourceName = dataSourceName; 
    6567    } 
    66     public String getIdColumn() { 
    67         return idColumn; 
    68     } 
    69     public void setIdColumn(String idColumn) { 
    70         this.idColumn = idColumn; 
     68    public void setIdField(String idField) { 
     69        this.idField= idField; 
    7170    } 
    7271    public String getName() { 
     
    108107        return forceExecuteScript; 
    109108    } 
     109    public String getPasswordField() { 
     110        return passwordField; 
     111    } 
     112     
     113    public void setPasswordField(String passwordField) { 
     114        this.passwordField = passwordField;    
     115    } 
     116    public String getIdField() { 
     117        return idField; 
     118    } 
    110119 
    111120} 
  • ECMPlatform/NXSQLDirectory/trunk/src/org/nuxeo/ecm/directory/sql/SQLSession.java

    r7823 r8073  
    6363    String dataSourceName; 
    6464 
    65     String idColumn
     65    String idField
    6666 
    6767    IdGenerator idGenerator; 
     
    8484        this.directory = directory; 
    8585        this.sqlConnection = sqlConnection; 
    86         this.schemaName = config.getSchemaName(); 
    87         this.tableName = config.getTableName(); 
    88         this.idColumn = config.getIdColumn(); 
    89         this.sid = SIDGenerator.next(); 
     86        schemaName = config.getSchemaName(); 
     87        tableName = config.getTableName(); 
     88        idField = config.getIdField(); 
     89 
     90        sid = SIDGenerator.next(); 
    9091        this.managedSQLSession = managedSQLSession; 
    9192 
    9293        this.idGenerator = idGenerator; 
    93         this.schema = NXCore.getTypeManager().getSchema(schemaName); 
    94         this.schemaFieldMap = new LinkedHashMap<String, Field>(); 
     94        schema = NXCore.getTypeManager().getSchema(schemaName); 
     95        schemaFieldMap = new LinkedHashMap<String, Field>(); 
    9596        for (Field f : schema.getFields()) { 
    9697            schemaFieldMap.put(f.getName().toString(), f); 
     
    106107        DataModel dataModel = new DataModelImpl(schemaName, fieldMap); 
    107108 
    108         String id = String.valueOf(fieldMap.get(idColumn)); 
     109        String id = String.valueOf(fieldMap.get(idField)); 
    109110        DocumentModelImpl docModel = new DocumentModelImpl(sid, schemaName, id, 
    110111                null, null, null, new String[] { schemaName }, null); 
     
    120121        if(idGenerator != null) { 
    121122            Integer idValue = idGenerator.nextId(); 
    122             fieldMap.put(idColumn, idValue); 
     123            fieldMap.put(idField, idValue); 
    123124        } 
    124125 
     
    149150 
    150151    public DocumentModel getEntry(String id) throws DirectoryException { 
    151         String sql = "select * from " + tableName + " where " + idColumn 
     152        String sql = "select * from " + tableName + " where " + idField 
    152153                + " = ?"; 
    153154        PreparedStatement ps; 
     
    199200            DataModel dataModel = docModel.getDataModel(schemaName); 
    200201            for (String fieldName : schemaFieldMap.keySet()) { 
    201                 if (fieldName.equals(idColumn)) { 
     202                if (fieldName.equals(idField)) { 
    202203                    continue; 
    203204                } 
     
    215216            String updateString = StringUtils.join(updateList.iterator(), ", "); 
    216217            String sql = "update " + tableName + " set " + updateString 
    217                     + " where " + idColumn + " = ?"; 
     218                    + " where " + idField + " = ?"; 
    218219            PreparedStatement ps = sqlConnection.prepareStatement(sql); 
    219220 
     
    221222            // TODO: how can I reset dirty fields? 
    222223            for (String fieldName : schemaFieldMap.keySet()) { 
    223                 if (fieldName.equals(idColumn)) { 
     224                if (fieldName.equals(idField)) { 
    224225                    continue; 
    225226                } 
     
    244245    public void deleteEntry(String id) throws UnsupportedOperationException, DirectoryException { 
    245246        try { 
    246             String sql = "delete from " + tableName + " where " + idColumn 
     247            String sql = "delete from " + tableName + " where " + idField 
    247248                    + "= ?"; 
    248249            PreparedStatement ps = sqlConnection.prepareStatement(sql); 
     
    425426 
    426427    public DocumentModelList query(Map<String, Object> filter, Set<String> fulltext) throws DirectoryException { 
    427         // TODO Auto-generated method stub 
    428         return null; 
     428        // XXX: temporary implementation to preserve compatibility 
     429        return query(filter); 
     430    } 
     431 
     432    public boolean authenticate(String username, String password) throws DirectoryException { 
     433        DocumentModel entry = getEntry(username); 
     434        if (entry == null) { 
     435            return false; 
     436        } 
     437        String storedPassword = (String) entry.getProperty(schemaName, 
     438                getPasswordField()); 
     439        return password.equals(storedPassword); 
     440    } 
     441 
     442    public boolean isAuthenticating() throws DirectoryException { 
     443        return schemaFieldMap.containsKey(getPasswordField()); 
     444    } 
     445 
     446    public String getIdField() { 
     447        return directory.config.getIdField(); 
     448    } 
     449 
     450    public String getPasswordField() { 
     451        return directory.config.getPasswordField(); 
    429452    } 
    430453 
  • ECMPlatform/NXSQLDirectory/trunk/src/org/nuxeo/ecm/directory/sql/SimpleDataSource.java

    r6697 r8073  
    3030 */ 
    3131public class SimpleDataSource implements DataSource { 
    32     private static Log log = LogFactory.getLog(SimpleDataSource.class); 
    33  
    3432    private String url; 
    3533    private String user; 
  • ECMPlatform/NXSQLDirectory/trunk/test/org/nuxeo/ecm/directory/sql/DirectoryTestCase.java

    r7683 r8073  
    4545        deploy("CoreService.xml"); 
    4646        deploy("TypeService.xml"); 
    47         deploy("RepositoryService.xml"); 
    48         deploy("CoreExtensions.xml"); 
    4947 
    5048        deploy("DirectoryTypes.xml"); 
  • ECMPlatform/NXSQLDirectory/trunk/test/org/nuxeo/ecm/directory/sql/TestAPI.java

    r7683 r8073  
    2626import org.nuxeo.ecm.core.api.DocumentModelList; 
    2727import org.nuxeo.ecm.directory.Session; 
    28 import org.nuxeo.ecm.directory.constants.UserDirectory; 
    2928 
    3029/** 
    31  * @author <a href="mailto:glefter@nuxeo.com">George Lefter</a> 
    32  * 
     30 * @author <a href="mailto:glefter@nuxeo.com">George Lefter</a> 
     31 *  
    3332 */ 
    3433public abstract class TestAPI extends DirectoryTestCase { 
     
    3736    private void insertRow() throws Exception { 
    3837        Connection con = getConnection(); 
    39         Statement stmt = con.createStatement(); 
    40         stmt.execute("insert into users(id, user, password) " + 
    41                    "values(1, 'user_1', 'pass_1')"); 
    42         stmt.execute("insert into t(user, password) " + 
    43         "values('user_1', 'pass_1')"); 
    44         con.commit(); 
    45         con.close(); 
     38        try { 
     39            Statement stmt = con.createStatement(); 
     40            stmt.execute("insert into users(username, password) " 
     41                    + "values('user_1', 'pass_1')"); 
     42            con.commit(); 
     43        } finally { 
     44            con.close(); 
     45        } 
    4646    } 
    4747 
     
    5252    private void clearTables() throws Exception { 
    5353        Connection con = getConnection(); 
    54         PreparedStatement stmt = con.prepareStatement("delete from users"); 
    55         stmt.execute(); 
    56         stmt = con.prepareStatement("delete from t"); 
    57         stmt.execute(); 
    58         con.commit(); 
    59         con.close(); 
     54        try { 
     55            PreparedStatement stmt = con.prepareStatement("delete from users"); 
     56            stmt.execute(); 
     57            con.commit(); 
     58        } finally { 
     59            con.close(); 
     60        } 
    6061    } 
    6162 
     
    6465 
    6566        Session session = getSession(); 
    66         assertNotNull(session); 
    67         Map<String, Object> map = new HashMap<String, Object>(); 
    68         map.put("user", "user_0"); 
    69         map.put("password", "pass_0"); 
    70         DocumentModel dm = session.createEntry(map); 
    71         assertNotNull(dm); 
    72  
    73         String id = dm.getId(); 
    74         assertNotNull(id); 
    75  
    76         String[] schemaNames = dm.getDeclaredSchemas(); 
    77         assertEquals(1, schemaNames.length); 
    78  
    79         assertEquals(schemaNames[0], schema); 
    80  
    81         assertEquals("user_0", dm.getProperty(schema, "user")); 
    82         assertEquals("pass_0", dm.getProperty(schema, "password")); 
    83  
    84         session.commit(); 
    85         session.close(); 
    86     } 
    87  
    88     public void testCreateEntryNotAutoincrement() throws Exception { 
    89         String myschema = "t"; 
    90         clearTables(); 
    91  
    92         Session session = getSession("t"); 
    93         assertNotNull(session); 
    94         Map<String, Object> map = new HashMap<String, Object>(); 
    95         map.put("user", "user_0"); 
    96         map.put("password", "pass_0"); 
    97         DocumentModel dm = session.createEntry(map); 
    98         assertNotNull(dm); 
    99  
    100         String id = dm.getId(); 
    101         assertNotNull(id); 
    102  
    103         String[] schemaNames = dm.getDeclaredSchemas(); 
    104         assertEquals(1, schemaNames.length); 
    105  
    106         assertEquals(schemaNames[0], myschema); 
    107  
    108         assertEquals("user_0", dm.getProperty(myschema, "user")); 
    109         assertEquals("pass_0", dm.getProperty(myschema, "password")); 
    110  
    111         session.commit(); 
    112         session.close(); 
     67        try { 
     68            assertNotNull(session); 
     69            Map<String, Object> map = new HashMap<String, Object>(); 
     70            map.put("username", "user_0"); 
     71            map.put("password", "pass_0"); 
     72            DocumentModel dm = session.createEntry(map); 
     73            assertNotNull(dm); 
     74     
     75            String id = dm.getId(); 
     76            assertEquals("user_0", id); 
     77     
     78            String[] schemaNames = dm.getDeclaredSchemas(); 
     79            assertEquals(1, schemaNames.length); 
     80     
     81            assertEquals(schemaNames[0], schema); 
     82     
     83            assertEquals("user_0", dm.getProperty(schema, "username")); 
     84            assertEquals("pass_0", dm.getProperty(schema, "password")); 
     85     
     86            session.commit(); 
     87        } finally { 
     88            session.close(); 
     89        } 
    11390    } 
    11491 
     
    11794        insertRow(); 
    11895 
    119  
    120         Session session = getSession(); 
    121         DocumentModel dm = session.getEntry("1"); 
    122  
    123         // update entry 
    124         dm.setProperty(schema, "user", "user_3"); 
    125         dm.setProperty(schema, "password", "pass_3"); 
    126         dm.setProperty(schema, "id", "3"); 
    127         session.updateEntry(dm); 
    128         session.commit(); 
    129         session.close(); 
    130  
    131         // retrieve entry again 
    132         // even if we tried to change the user_id, it should not be changed 
     96        Session session = getSession(); 
     97        try { 
     98            DocumentModel dm = session.getEntry("user_1"); 
     99     
     100            // update entry 
     101            dm.setProperty(schema, "username", "user_2"); 
     102            dm.setProperty(schema, "password", "pass_2"); 
     103            session.updateEntry(dm); 
     104            session.commit(); 
     105            session.close(); 
     106     
     107            // retrieve entry again 
     108            // even if we tried to change the user id (username), it should 
     109            // not be changed 
     110     
     111            session = getSession(); 
     112            dm = session.getEntry("user_1"); 
     113            assertEquals("user_1", dm.getProperty(schema, "username")); 
     114            assertEquals("pass_2", dm.getProperty(schema, "password")); 
     115            assertEquals(null, session.getEntry("user_2")); 
     116        } finally { 
     117            session.close(); 
     118        } 
     119    } 
     120 
     121    public void testDeleteEntry() throws Exception { 
     122        clearTables(); 
     123        insertRow(); 
     124        Session session = getSession(); 
     125        try { 
     126            DocumentModel dm = session.getEntry("user_1"); 
     127            session.deleteEntry(dm); 
     128            session.commit(); 
     129            session.close(); 
     130     
     131            session = getSession(); 
     132            dm = session.getEntry("user_1"); 
     133            assertNull(dm); 
     134        } finally { 
     135            session.close(); 
     136        } 
     137    } 
     138 
     139    public void testRollback() throws Exception { 
     140        clearTables(); 
     141        insertRow(); 
     142        Session session = getSession(); 
     143        try { 
     144            DocumentModel dm = session.getEntry("user_1"); 
     145            session.deleteEntry(dm); 
     146            session.rollback(); 
     147        } finally { 
     148            session.close(); 
     149        } 
    133150 
    134151        session = getSession(); 
    135         dm = session.getEntry("1"); 
    136         assertEquals("user_3", dm.getProperty(schema, "user")); 
    137         assertEquals("pass_3", dm.getProperty(schema, "password")); 
    138     } 
    139  
    140     public void testUpdateEntryNotAutoincrement() throws Exception { 
    141         String myschema="t"; 
    142         clearTables(); 
    143         insertRow(); 
    144  
    145  
    146         Session session = getSession("t"); 
    147         DocumentModel dm = session.getEntry("user_1"); 
    148  
    149         assertNotNull(dm); 
    150  
    151         // update entry 
    152         dm.setProperty(myschema, "user", "user_3"); 
    153         dm.setProperty(myschema, "password", "pass_3"); 
    154         session.updateEntry(dm); 
    155         session.commit(); 
    156         session.close(); 
    157  
    158         // retrieve entry again 
    159         // even if we tried to change the user_id, it should not be changed 
    160  
    161         session = getSession(myschema); 
    162         dm = session.getEntry("user_1"); 
    163         assertEquals("pass_3", dm.getProperty(myschema, "password")); 
    164     } 
    165  
    166     public void testDeleteEntry() throws Exception { 
    167         clearTables(); 
    168         insertRow(); 
    169         Session session = getSession(); 
    170         DocumentModel dm = session.getEntry("1"); 
    171         session.deleteEntry(dm); 
    172         session.commit(); 
    173         session.close(); 
    174  
    175         session = getSession(); 
    176         dm = session.getEntry("1"); 
    177         assertNull(dm); 
    178     } 
    179  
    180     public void testDeleteEntryNotAutoincrement() throws Exception { 
    181         String myschema="t"; 
    182         clearTables(); 
    183         insertRow(); 
    184         Session session = getSession("t"); 
    185         DocumentModel dm = session.getEntry("user_1"); 
    186         session.deleteEntry(dm); 
    187         session.commit(); 
    188         session.close(); 
    189  
    190         session = getSession("t"); 
    191         dm = session.getEntry("user_1"); 
    192         assertNull(dm); 
    193     } 
    194  
    195     public void testRollback() throws Exception { 
    196         clearTables(); 
    197         insertRow(); 
    198         Session session = getSession(); 
    199         DocumentModel dm = session.getEntry("1"); 
    200         session.deleteEntry(dm); 
    201         session.rollback(); 
    202         session.close(); 
    203  
    204         session = getSession(); 
    205         dm = session.getEntry("1"); 
    206         assertNotNull(dm); 
    207         session.close(); 
     152        try { 
     153            DocumentModel dm = session.getEntry("user_1"); 
     154            assertNotNull(dm); 
     155        } finally { 
     156            session.close(); 
     157        } 
    208158    } 
    209159 
     
    212162        insertRow(); 
    213163        Session session = getSession(); 
    214         Map<String, Object> filter = new HashMap<String, Object>(); 
    215         filter.put("user", "user_1"); 
    216         filter.put("password", "pass_1"); 
    217         DocumentModelList list = session.query(filter); 
    218         assertEquals(1, list.size()); 
    219         DocumentModel docModel = list.get(0); 
    220         assertNotNull(docModel); 
    221         assertEquals("user_1", docModel.getProperty(schema, "user")); 
    222         assertEquals("pass_1", docModel.getProperty(schema, "password")); 
     164        try { 
     165            Map<String, Object> filter = new HashMap<String, Object>(); 
     166            filter.put("username", "user_1"); 
     167            filter.put("password", "pass_1"); 
     168            DocumentModelList list = session.query(filter); 
     169            assertEquals(1, list.size()); 
     170            DocumentModel docModel = list.get(0); 
     171            assertNotNull(docModel); 
     172            assertEquals("user_1", docModel.getProperty(schema, "username")); 
     173            assertEquals("pass_1", docModel.getProperty(schema, "password")); 
     174        } finally { 
     175            session.close(); 
     176        } 
    223177    } 
    224178 
     
    227181        insertRow(); 
    228182        Session session = getSession(); 
    229         Map<String, Object> filter = new HashMap<String, Object>(); 
    230         filter.put("user", "user_1"); 
    231         filter.put("password", "pass_x"); // no such password 
    232         DocumentModelList list = session.query(filter); 
    233         assertEquals(0, list.size()); 
     183        try { 
     184            Map<String, Object> filter = new HashMap<String, Object>(); 
     185            filter.put("username", "user_1"); 
     186            filter.put("password", "pass_x"); // no such password 
     187            DocumentModelList list = session.query(filter); 
     188            assertEquals(0, list.size()); 
     189        } finally { 
     190            session.close(); 
     191        } 
    234192    } 
    235193 
     
    238196        insertRow(); 
    239197        Session session = getSession(); 
    240         Map<String, Object> filter = new HashMap<String, Object>(); 
    241         filter.put("user", "user_1"); 
    242         List<String> list = session.getProjection(filter, "password"); 
    243         assertEquals(1, list.size()); 
    244         assertTrue(list.contains("pass_1")); 
     198        try { 
     199            Map<String, Object> filter = new HashMap<String, Object>(); 
     200            filter.put("username", "user_1"); 
     201            List<String> list = session.getProjection(filter, "password"); 
     202            assertEquals(1, list.size()); 
     203            assertTrue(list.contains("pass_1")); 
     204        } finally { 
     205            session.close(); 
     206        } 
    245207    } 
    246208 
     
    249211        insertRow(); 
    250212        Session session = getSession(); 
    251         Map<String, Object> filter = new HashMap<String, Object>(); 
    252         filter.put("user", "user_1"); 
    253         String password = session.getUniqueProjection(filter, "id"); 
    254         assertEquals(password, "1"); 
     213        try { 
     214            Map<String, Object> filter = new HashMap<String, Object>(); 
     215            filter.put("username", "user_1"); 
     216            String password = session.getUniqueProjection(filter, "password"); 
     217            assertEquals(password, "pass_1"); 
     218        } finally { 
     219            session.close(); 
     220        } 
    255221    } 
    256222 
     
    259225        insertRow(); 
    260226        Session session = getSession(); 
    261         Map<String, Object> filter = new HashMap<String, Object>(); 
    262         filter.put("id", "1"); 
    263         String password = session.getUniqueProjection(filter, "user"); 
    264         assertEquals(password, "user_1"); 
     227        try { 
     228            Map<String, Object> filter = new HashMap<String, Object>(); 
     229            filter.put("password", "pass_1"); 
     230            String username = session.getUniqueProjection(filter, "username"); 
     231            assertEquals(username, "user_1"); 
     232        } finally { 
     233            session.close(); 
     234        } 
    265235    } 
    266236 
     
    269239        insertRow(); 
    270240        Session session = getSession(); 
    271         Map<String, Object> filter = new HashMap<String, Object>(); 
    272  
    273         filter.put(UserDirectory.USER_COLUMN, "u*"); 
    274         List<String> users = session.getProjection(filter, UserDirectory.USER_COLUMN); 
    275         assertTrue(users!=null); 
    276         assertTrue(users.contains("user_1")); 
    277  
    278         filter.put(UserDirectory.USER_COLUMN, "v*"); 
    279         users = session.getProjection(filter, UserDirectory.USER_COLUMN); 
    280         assertTrue(users!=null); 
    281         assertFalse(users.contains("user_1")); 
    282  
    283         filter.put(UserDirectory.USER_COLUMN, "*"); 
    284         users = session.getProjection(filter, UserDirectory.USER_COLUMN); 
    285         assertTrue(users!=null); 
    286         assertTrue(users.contains("user_1")); 
    287  
    288     } 
    289  
     241        try { 
     242            Map<String, Object> filter = new HashMap<String, Object>(); 
     243     
     244            filter.put("username", "u*"); 
     245            List<String> users = session.getProjection(filter, 
     246                    "username"); 
     247            assertTrue(users != null); 
     248            assertTrue(users.contains("user_1")); 
     249     
     250            filter.put("username", "v*"); 
     251            users = session.getProjection(filter, "username"); 
     252            assertTrue(users != null); 
     253            assertFalse(users.contains("user_1")); 
     254     
     255            filter.put("username", "*"); 
     256            users = session.getProjection(filter, "username"); 
     257            assertTrue(users != null); 
     258            assertTrue(users.contains("user_1")); 
     259        } finally { 
     260            session.close(); 
     261        } 
     262    } 
     263 
     264    public void testIsAuthenticating() throws Exception { 
     265        Session session = getSession(); 
     266        try { 
     267            // by default the user directory is authenticating 
     268            assertTrue(session.isAuthenticating()); 
     269 
     270            // by setting a pasword field that does not belong to the 
     271            // user schema, we disable that feature 
     272            SQLDirectory directory = (SQLDirectory) session.getDirectory(); 
     273            directory.config.setPasswordField("SomeStrangePassordField"); 
     274 
     275            assertFalse(session.isAuthenticating()); 
     276 
     277        } finally { 
     278            session.close(); 
     279        } 
     280    } 
     281 
     282    public void testAuthenticate() throws Exception { 
     283        Session session = getSession(); 
     284        try { 
     285            // successful authentication 
     286            assertTrue(session.authenticate("Administrator", "Administrator")); 
     287            assertTrue(session.authenticate("user", "user")); 
     288 
     289            // failed authentication: bad password 
     290            assertFalse(session.authenticate("Administrator", "WrongPassword")); 
     291            assertFalse(session.authenticate("user", ".asdf'23423")); 
     292 
     293            // failed authentication: not existing user 
     294            assertFalse(session.authenticate("NonExistingUser", "whatever")); 
     295 
     296        } finally { 
     297            session.close(); 
     298        } 
     299    } 
    290300} 
  • ECMPlatform/NXSQLDirectory/trunk/test/resources/CoreDirectories-bundle.xml

    r7683 r8073  
    1414 
    1515            <table>users</table> 
    16             <idColumn>id</idColumn> 
    17             <autoincrementIdColumn>true</autoincrementIdColumn> 
     16            <idField>username</idField> 
     17            <passwordField>password</passwordField> 
     18             
     19            <autoincrementIdField>false</autoincrementIdField> 
    1820            <sqlScript>setup-hsqldb.sql</sqlScript> 
    1921            <forceExecuteScript>true</forceExecuteScript> 
     
    2931 
    3032            <table>groups</table> 
    31             <idColumn>id</idColumn
    32             <autoincrementIdColumn>true</autoincrementIdColumn
     33            <idField>id</idField
     34            <autoincrementIdField>true</autoincrementIdField
    3335        </directory> 
    3436 
     
    4244 
    4345            <table>roles</table> 
    44             <idColumn>id</idColumn
    45             <autoincrementIdColumn>true</autoincrementIdColumn
     46            <idField>id</idField
     47            <autoincrementIdField>true</autoincrementIdField
    4648        </directory> 
    4749        <directory name="user2roleDirectory"> 
     
    5456 
    5557            <table>user2role</table> 
    56             <idColumn>id</idColumn
    57             <autoincrementIdColumn>true</autoincrementIdColumn
     58            <idField>id</idField
     59            <autoincrementIdField>true</autoincrementIdField
    5860        </directory> 
    5961        <directory name="user2groupDirectory"> 
     
    6668 
    6769            <table>user2group</table> 
    68             <idColumn>id</idColumn
    69             <autoincrementIdColumn>true</autoincrementIdColumn
     70            <idField>id</idField
     71            <autoincrementIdField>true</autoincrementIdField
    7072        </directory> 
    7173        <directory name="group2groupDirectory"> 
     
    7880            <dbPassword></dbPassword> 
    7981 
    80             <idColumn>id</idColumn
    81             <autoincrementIdColumn>true</autoincrementIdColumn
     82            <idField>id</idField
     83            <autoincrementIdField>true</autoincrementIdField
    8284        </directory> 
    8385        <directory name="t"> 
     
    8991            <dbUser>sa</dbUser> 
    9092            <dbPassword></dbPassword> 
    91             <idColumn>user</idColumn
     93            <idField>user</idField
    9294        </directory> 
    9395     </extension> 
  • ECMPlatform/NXSQLDirectory/trunk/test/resources/DirectoryTypes.xml

    r7683 r8073  
    66        <schema name="group" src="schema/group.xsd"/> 
    77        <schema name="role" src="schema/role.xsd"/> 
    8         <schema name="t" src="schema/t.xsd"/> 
    98    </extension> 
    109 
     
    2019            <schema name="role"/> 
    2120        </doctype> 
    22         <doctype name="T" extends="Document"> 
    23             <schema name="t"/> 
    24         </doctype> 
    2521    </extension> 
    2622 
  • ECMPlatform/NXSQLDirectory/trunk/test/resources/schema/group.xsd

    r6622 r8073  
    66        > 
    77 
    8         <xs:element name="id" type="xs:integer"/> 
    9        <xs:element name="xgroup" type="xs:string"/> 
     8        <xs:element name="groupname" type="xs:string"/> 
     9    <xs:element name="description" type="xs:string"/> 
    1010 
    1111</xs:schema> 
  • ECMPlatform/NXSQLDirectory/trunk/test/resources/schema/role.xsd

    r6622 r8073  
    66        > 
    77 
    8         <xs:element name="id" type="xs:integer"/> 
    9        <xs:element name="role" type="xs:string"/> 
     8        <xs:element name="rolename" type="xs:string"/> 
     9    <xs:element name="description" type="xs:string"/> 
    1010 
    1111</xs:schema> 
  • ECMPlatform/NXSQLDirectory/trunk/test/resources/schema/user.xsd

    r6164 r8073  
    66        > 
    77         
    8          
    9         <xs:element name="id" type="xs:integer"/> 
    10         <xs:element name="user" type="xs:string"/> 
     8        <xs:element name="username" type="xs:string"/> 
    119        <xs:element name="password" type="xs:string"/> 
    1210        <xs:element name="firstName" type="xs:string"/> 
  • ECMPlatform/NXSQLDirectory/trunk/test/resources/schema/user2group.xsd

    r6227 r8073  
    88         
    99        <xs:element name="id" type="xs:integer"/> 
    10         <xs:element name="userId" type="xs:integer"/> 
    11         <xs:element name="groupId" type="xs:integer"/> 
     10        <xs:element name="userId" type="xs:string"/> 
     11        <xs:element name="groupId" type="xs:string"/> 
    1212 
    1313</xs:schema> 
  • ECMPlatform/NXSQLDirectory/trunk/test/resources/schema/user2role.xsd

    r6227 r8073  
    88         
    99        <xs:element name="id" type="xs:integer"/> 
    10         <xs:element name="userId" type="xs:integer"/> 
    11         <xs:element name="roleId" type="xs:integer"/> 
     10        <xs:element name="userId" type="xs:string"/> 
     11        <xs:element name="roleId" type="xs:string"/> 
    1212 
    1313</xs:schema> 
  • ECMPlatform/NXSQLDirectory/trunk/test/resources/setup-hsqldb.sql

    r7683 r8073  
    11DROP TABLE users IF EXISTS; 
    22CREATE TABLE users ( 
    3   id integer NOT NULL, 
    4   user char(200), 
    5   password char(200), 
    6   firstName char(200), 
    7   lastName char(200), 
    8   company char(200), 
    9   PRIMARY KEY(id) 
     3  username varchar(200), 
     4  password varchar(200), 
     5  firstName varchar(200), 
     6  lastName varchar(200), 
     7  company varchar(200), 
     8  PRIMARY KEY(username) 
    109); 
    1110 
    12 INSERT INTO users(id, user, password) VALUES (1, 'useradmin', 'useradmin'); 
    13 INSERT INTO users(id, user, password) VALUES (2, 'user','user'); 
    14 INSERT INTO users(id, user, password) VALUES (3, 'q','q'); 
    15 INSERT INTO users(id, user, password) VALUES (5, 'Administrator', 'Administrator'); 
     11INSERT INTO users(username, password) VALUES ('useradmin', 'useradmin'); 
     12INSERT INTO users(username, password) VALUES ('user','user'); 
     13INSERT INTO users(username, password) VALUES ('user2','user2'); 
     14INSERT INTO users(username, password) VALUES ('Administrator', 'Administrator'); 
    1615 
    1716DROP TABLE roles IF EXISTS; 
    1817CREATE TABLE roles ( 
    19   id integer NOT NULL
    20   role varchar(200), 
    21   PRIMARY KEY (id
     18  rolename varchar(200)
     19  description varchar(500), 
     20  PRIMARY KEY (rolename
    2221); 
    2322 
    24 INSERT INTO roles values(1, 'regular'); 
    25 INSERT INTO roles values(2, 'admin'); 
    26  
     23INSERT INTO roles values('regular', 'Some role'); 
     24INSERT INTO roles values('admin', 'The Administration role'); 
    2725 
    2826DROP TABLE user2role IF EXISTS; 
    2927CREATE TABLE user2role ( 
    3028  id integer NOT NULL, 
    31   userId integer NOT NULL, 
    32   roleId integer NOT NULL, 
     29  userId varchar(200) NOT NULL, 
     30  roleId varchar(200) NOT NULL, 
    3331  PRIMARY KEY (id) 
    3432); 
    3533 
    36 INSERT INTO user2role VALUES (1,1,2); 
    37 INSERT INTO user2role VALUES (2,1,1); 
    38 INSERT INTO user2role VALUES (3,2,1); 
    39 INSERT INTO user2role VALUES (4,3,2); 
    40 INSERT INTO user2role VALUES (5,3,1); 
    41 INSERT INTO user2role VALUES (7,5,1); 
    42 INSERT INTO user2role VALUES (8,5,2); 
     34INSERT INTO user2role VALUES (1, 'useradmin', 'admin'); 
     35INSERT INTO user2role VALUES (2, 'useradmin', 'regular'); 
     36INSERT INTO user2role VALUES (3, 'user', 'regular'); 
     37INSERT INTO user2role VALUES (4, 'user2', 'admin'); 
     38INSERT INTO user2role VALUES (5, 'user2', 'regular'); 
     39INSERT INTO user2role VALUES (7, 'Administrator', 'regular'); 
     40INSERT INTO user2role VALUES (8, 'Administrator', 'admin'); 
    4341 
    4442DROP TABLE groups IF EXISTS; 
    4543CREATE TABLE groups ( 
    46   id integer NOT NULL
    47   xgroup char(200), 
    48   PRIMARY KEY(id
     44  groupname varchar(200)
     45  description varchar(500), 
     46  PRIMARY KEY(groupname
    4947); 
    5048 
    51 INSERT INTO groups VALUES(1, 'members'); 
    52 INSERT INTO groups VALUES(2, 'administrators'); 
     49INSERT INTO groups VALUES('members', 'The group of members'); 
     50INSERT INTO groups VALUES('administrators', 'The group of administrators'); 
    5351 
    5452DROP TABLE user2group IF EXISTS; 
    5553CREATE TABLE user2group ( 
    5654  id integer NOT NULL, 
    57   userId integer NOT NULL, 
    58   groupId integer NOT NULL, 
     55  userId varchar(200) NOT NULL, 
     56  groupId varchar(200) NOT NULL, 
    5957  PRIMARY KEY(id) 
    6058); 
    6159 
    62 INSERT INTO user2group VALUES(1, 1, 1); 
    63 INSERT INTO user2group VALUES(2, 2, 1); 
    64 INSERT INTO user2group VALUES(3, 3, 1); 
    65 INSERT INTO user2group VALUES(5, 5, 1); 
    66 INSERT INTO user2group VALUES(6, 5, 2); 
     60INSERT INTO user2group VALUES(1, 'useradmin', 'members'); 
     61INSERT INTO user2group VALUES(2, 'user', 'members'); 
     62INSERT INTO user2group VALUES(3, 'user2', 'members'); 
     63INSERT INTO user2group VALUES(5, 'Administrator', 'members'); 
     64INSERT INTO user2group VALUES(6, 'Administrator', 'administrators'); 
    6765 
    6866DROP TABLE group2group IF EXISTS; 
    6967CREATE TABLE group2group ( 
    7068  id integer NOT NULL, 
    71   parentGroupId integer NOT NULL, 
    72   childGroupId integer NOT NULL, 
     69  parentGroupId varchar(200) NOT NULL, 
     70  childGroupId varchar(200) NOT NULL, 
    7371  PRIMARY KEY(id) 
    7472); 
    75  
    76 DROP TABLE t IF EXISTS; 
    77 CREATE TABLE t ( 
    78   user char(200), 
    79   password char(200), 
    80   firstName char(200), 
    81   lastName char(200), 
    82   company char(200), 
    83   PRIMARY KEY(user) 
    84 ); 
    85  
    86 INSERT INTO t(user, password) VALUES ('useradmin', 'useradmin'); 
    87 INSERT INTO t(user, password) VALUES ('user','user'); 
    88 INSERT INTO t(user, password) VALUES ('q','q'); 
    89 INSERT INTO t(user, password) VALUES ('Administrator', 'Administrator'); 
  • ECMPlatform/NXUserManagerImpl/trunk/src/org/nuxeo/ecm/platform/ec/usermanager/UserManagerImpl.java

    r7141 r8073  
    2222import org.nuxeo.ecm.directory.constants.Group2GroupDirectory; 
    2323import org.nuxeo.ecm.directory.constants.GroupDirectory; 
    24 import org.nuxeo.ecm.directory.constants.RoleDirectory; 
    2524import org.nuxeo.ecm.directory.constants.User2GroupDirectory; 
    26 import org.nuxeo.ecm.directory.constants.User2RoleDirectory; 
    2725import org.nuxeo.ecm.directory.constants.UserDirectory; 
    28 import org.nuxeo.ecm.directory.UniqueResultException; 
    2926import org.nuxeo.ecm.platform.ec.usermanager.NuxeoPrincipalImpl; 
    3027 
     
    4037    /* 
    4138     * (non-Javadoc) 
     39     *  
    4240     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#remove() 
    4341     */ 
     
    4846    /* 
    4947     * (non-Javadoc) 
    50      * 
     48     *  
    5149     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#checkUsernamePassword(java.lang.String, 
    5250     *      java.lang.String) 
     
    6159        DirectoryClient userDir = null; 
    6260        try { 
    63             Map<String, Object> filter = new HashMap<String, Object>(); 
    64             filter.put(UserDirectory.USER_COLUMN, user); 
    65  
    6661            userDir = dirInstance.open(UserDirectory.DIRECTORY_NAME); 
    67             DocumentModelList docModelList = userDir.query(filter); 
    68             if (docModelList.size() != 1) { 
    69                 // query on database returned zero or many results 
     62            if (!userDir.isAuthenticating()) { 
     63                log.error("trying to authenticate against a non authenticating" 
     64                        + "directory: " + userDir.getDirectoryName()); 
    7065                return false; 
    7166            } 
    72             DocumentModel docModel = docModelList.get(0); 
    73  
    74             String dbUsername = (String) docModel.getProperty("user", 
    75                     UserDirectory.USER_COLUMN); 
    76             String dbPassword = (String) docModel.getProperty("user", 
    77                     UserDirectory.PASSWORD_COLUMN); 
    78  
    79             if (password.equals(dbPassword) && user.equals(dbUsername)) { 
    80                 return true; 
    81             } else { 
    82                 return false; 
    83             } 
     67            return userDir.authenticate(user, password); 
    8468        } finally { 
    8569            if (userDir != null) { 
     
    9478            // check if the user exists 
    9579            userDir = dirInstance.open(UserDirectory.DIRECTORY_NAME); 
    96             Map<String, Object> filter = new HashMap<String, Object>(); 
    97             filter.put(UserDirectory.USER_COLUMN, username); 
    98  
    99             DocumentModelList principals = userDir.query(filter); 
    100  
    101             if (principals.size() == 0) { 
    102                 return null; 
    103             } else if (principals.size() > 1) { 
    104                 throw new DirectoryException( 
    105                         "multiple entries found in user table for username: " 
    106                                 + username); 
    107             } 
    108  
    109             DocumentModel docModel = principals.get(0); 
     80            DocumentModel docModel = userDir.getEntry(username); 
    11081 
    11182            NuxeoPrincipalImpl principal = new NuxeoPrincipalImpl(username); 
     
    12293 
    12394            List<String> groups = getGroupsForUser(username); 
    124             List<String> roles = getRolesForUser(username); 
    12595            principal.setGroups(groups); 
     96            // TODO: renable roles initialzation once we have a use case for 
     97            // a role directory. In the mean time we only set the JBOSS role that 
     98            // is required to login 
     99            List<String> roles = new ArrayList<String>(); 
     100            roles.add("regular"); 
    126101            principal.setRoles(roles); 
    127102 
     
    152127            // update the user entry 
    153128            String schema = userDir.getDirectorySchema(); 
    154  
    155             Map<String, Object> filter = new HashMap<String, Object>(); 
    156             filter.put(UserDirectory.USER_COLUMN, principalName); 
    157             DocumentModel docModel = userDir.query(filter).get(0); 
     129            DocumentModel docModel = userDir.getEntry(principalName); 
    158130            boolean docModelModified = false; 
    159131 
    160             if (!StringUtils.equals(principal.getFirstName(), oldPrincipal.getFirstName())) { 
    161                 docModel.setProperty(schema, 
    162                         UserDirectory.FIRSTNAME_COLUMN, 
     132            if (!StringUtils.equals(principal.getFirstName(), oldPrincipal 
     133                    .getFirstName())) { 
     134                docModel.setProperty(schema, UserDirectory.FIRSTNAME_COLUMN, 
    163135                        principal.getFirstName()); 
    164136                docModelModified = true; 
    165137            } 
    166138 
    167             if (!StringUtils.equals(principal.getLastName(), oldPrincipal.getLastName())) { 
    168                 docModel.setProperty(schema, 
    169                         UserDirectory.LASTNAME_COLUMN, 
     139            if (!StringUtils.equals(principal.getLastName(), oldPrincipal 
     140                    .getLastName())) { 
     141                docModel.setProperty(schema, UserDirectory.LASTNAME_COLUMN, 
    170142                        principal.getLastName()); 
    171143                docModelModified = true; 
    172144            } 
    173145 
    174             if (!StringUtils.equals(principal.getCompany(), oldPrincipal.getCompany())) { 
    175                 docModel.setProperty(schema, 
    176                         UserDirectory.COMPANY_COLUMN, 
     146            if (!StringUtils.equals(principal.getCompany(), oldPrincipal 
     147                    .getCompany())) { 
     148                docModel.setProperty(schema, UserDirectory.COMPANY_COLUMN, 
    177149                        principal.getCompany()); 
    178150                docModelModified = true; 
    179151            } 
    180152 
    181             if( principal.getPassword()!=null) { 
    182                 docModel.setProperty(schema, 
    183                         UserDirectory.PASSWORD_COLUMN, 
     153            if (principal.getPassword() != null) { 
     154                docModel.setProperty(schema, userDir.getPasswordField(), 
    184155                        principal.getPassword()); 
    185156                docModelModified = true; 
    186157            } 
    187158 
    188             if(docModelModified) { 
     159            if (docModelModified) { 
    189160                userDir.updateEntry(docModel); 
    190161            } 
     
    198169            removedRoles.removeAll(newRoles); 
    199170 
    200             for(String roleName: addedRoles) { 
     171            for (String roleName : addedRoles) { 
    201172                addPrincipalToRole(principalName, roleName); 
    202173            } 
    203             for(String roleName: removedRoles) { 
     174            for (String roleName : removedRoles) { 
    204175                removePrincipalFromRole(principalName, roleName); 
    205176            } 
     
    214185            removedGroups.removeAll(newGroups); 
    215186 
    216             for(String groupName: addedGroups) { 
     187            for (String groupName : addedGroups) { 
    217188                addPrincipalToGroup(principalName, groupName); 
    218189            } 
    219             for(String groupName: removedGroups) { 
     190            for (String groupName : removedGroups) { 
    220191                removePrincipalFromGroup(principalName, groupName); 
    221192            } 
     
    230201    } 
    231202 
    232     public void updateGroup(NuxeoGroup group) throws ClientException
     203    public void updateGroup(NuxeoGroup group) throws ClientException
    233204        String groupName = group.getName(); 
    234205        NuxeoGroup oldGroup = getGroup(groupName); 
     
    239210        List<String> addedUsers = new ArrayList<String>(newUsers); 
    240211        addedUsers.removeAll(oldUsers); 
    241         for(String principalName: addedUsers) { 
     212        for (String principalName : addedUsers) { 
    242213            addPrincipalToGroup(principalName, groupName); 
    243214        } 
     
    245216        List<String> removedUsers = new ArrayList<String>(oldUsers); 
    246217        removedUsers.removeAll(newUsers); 
    247         for(String principalName: removedUsers) { 
     218        for (String principalName : removedUsers) { 
    248219            removePrincipalFromGroup(principalName, groupName); 
    249220        } 
     
    253224        List<String> addedGroups = new ArrayList<String>(newGroups); 
    254225        addedGroups.removeAll(oldGroups); 
    255         for(String childGroupName: addedGroups) { 
     226        for (String childGroupName : addedGroups) { 
    256227            addGroupToGroup(childGroupName, groupName); 
    257228        } 
     
    259230        List<String> removedGroups = new ArrayList<String>(oldGroups); 
    260231        removedGroups.removeAll(newGroups); 
    261         for(String childGroupName: removedGroups) { 
     232        for (String childGroupName : removedGroups) { 
    262233            removeGroupFromGroup(childGroupName, groupName); 
    263234        } 
     
    265236    } 
    266237 
    267     public NuxeoGroup getGroup(String groupName) throws ClientException { 
    268         NuxeoGroup group = new NuxeoGroupImpl(groupName); 
     238    public NuxeoGroup getGroup(String groupId) throws ClientException { 
     239        NuxeoGroup group = new NuxeoGroupImpl(groupId); 
    269240        DirectoryClient groupDir = null; 
    270241        try { 
    271242            groupDir = dirInstance.open(GroupDirectory.DIRECTORY_NAME); 
    272243 
    273             HashMap<String, Object> filter = new HashMap<String, Object>(); 
    274             filter.put(GroupDirectory.GROUP_COLUMN, groupName); 
    275             List<String> groupIds = groupDir.getProjection(filter, 
    276                     GroupDirectory.ID_COLUMN); 
    277             if(groupIds.size()!=1) { 
    278                 // no group found 
     244            // check that the group exists 
     245            // TODO: use hasEntry 
     246            if (groupDir.getEntry(groupId) == null) { 
    279247                return null; 
    280248            } 
    281249 
    282             List<String> groupNames = getGroupsInGroup(groupName); 
    283             List<String> principalNames = getPrincipalsInGroup(groupName); 
    284             group.setMemberGroups(groupNames); 
    285             group.setMemberUsers(principalNames); 
     250            List<String> groupIds = getGroupsInGroup(groupId); 
     251            List<String> principalIds = getPrincipalsInGroup(groupId); 
     252            group.setMemberGroups(groupIds); 
     253            group.setMemberUsers(principalIds); 
    286254 
    287255            return group; 
    288256        } finally { 
    289             if(groupDir!=null) { 
     257            if (groupDir != null) { 
    290258                groupDir.close(); 
    291             } 
    292        } 
    293     } 
    294  
    295     /** 
    296      * Get the roles the current user belongs to 
    297      */ 
    298     private List<String> getRolesForUser(String username) 
    299             throws DirectoryException { 
    300         DirectoryClient roleDir = null; 
    301         DirectoryClient userDir = null; 
    302         DirectoryClient user2roleDir = null; 
    303         try { 
    304             roleDir = dirInstance.open(RoleDirectory.DIRECTORY_NAME); 
    305             userDir = dirInstance.open(UserDirectory.DIRECTORY_NAME); 
    306             user2roleDir = dirInstance.open(User2RoleDirectory.DIRECTORY_NAME); 
    307  
    308             HashMap<String, Object> filter = new HashMap<String, Object>(); 
    309             filter.put(UserDirectory.USER_COLUMN, username); 
    310  
    311             // get userId 
    312             String userId = userDir.getUniqueProjection(filter, 
    313                     UserDirectory.ID_COLUMN); 
    314  
    315             // get role ids 
    316             filter.clear(); 
    317             filter.put(User2RoleDirectory.USERID_COLUMN, userId); 
    318             List<String> roleIds = user2roleDir.getProjection(filter, 
    319                     User2RoleDirectory.ROLEID_COLUMN); 
    320  
    321             // get role names 
    322             List<String> roleNames = new ArrayList<String>(); 
    323             for (String roleId : roleIds) { 
    324                 filter.clear(); 
    325                 filter.put(RoleDirectory.ID_COLUMN, roleId); 
    326                 String roleName = roleDir.getUniqueProjection(filter, 
    327                         RoleDirectory.ROLE_COLUMN); 
    328                 roleNames.add(roleName); 
    329             } 
    330  
    331             return roleNames; 
    332  
    333         } finally { 
    334             if (roleDir != null) { 
    335                 roleDir.close(); 
    336             } 
    337             if (userDir != null) { 
    338                 userDir.close(); 
    339             } 
    340             if (user2roleDir != null) { 
    341                 user2roleDir.close(); 
    342259            } 
    343260        } 
     
    358275                    .open(User2GroupDirectory.DIRECTORY_NAME); 
    359276 
     277            // TODO: refactor using idField property 
    360278            HashMap<String, Object> filter = new HashMap<String, Object>(); 
    361             filter.put(UserDirectory.USER_COLUMN, username); 
    362  
    363             // get userId 
    364             String userId = userDir.getUniqueProjection(filter, 
    365                     UserDirectory.ID_COLUMN); 
    366  
    367             // get group ids 
    368             filter.clear(); 
    369             filter.put(User2GroupDirectory.USERID_COLUMN, userId); 
     279            filter.put(User2GroupDirectory.USERID_COLUMN, username); 
    370280            List<String> groupIds = user2groupDir.getProjection(filter, 
    371281                    User2GroupDirectory.GROUPID_COLUMN); 
    372282 
    373             // get group names 
    374             List<String> groupNames = new ArrayList<String>(); 
    375             for (String groupId : groupIds) { 
    376                 filter.clear(); 
    377                 filter.put(GroupDirectory.ID_COLUMN, groupId); 
    378                 String groupName = groupDir.getUniqueProjection(filter, 
    379                         GroupDirectory.GROUP_COLUMN); 
    380  
    381                 groupNames.add(groupName); 
    382             } 
    383  
    384             return groupNames; 
     283            return groupIds; 
    385284 
    386285        } finally { 
     
    399298    /* 
    400299     * (non-Javadoc) 
    401      * 
     300     *  
    402301     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#addGroupMember(java.lang.String, 
    403302     *      java.lang.String) 
    404303     */ 
    405     private void addGroupToGroup(String childGroupName, String groupName
     304    private void addGroupToGroup(String childId, String parentId
    406305            throws ClientException { 
    407306 
    408307        DirectoryClient group2groupDir = null; 
    409         DirectoryClient groupDir = null; 
    410         HashMap<String, Object> filter = new HashMap<String, Object>(); 
    411         try { 
    412             groupDir = dirInstance.open(GroupDirectory.DIRECTORY_NAME); 
     308        try { 
    413309            group2groupDir = dirInstance 
    414310                    .open(Group2GroupDirectory.DIRECTORY_NAME); 
    415311 
    416             // get groupId 
    417             filter.clear(); 
    418             filter.put(GroupDirectory.GROUP_COLUMN, groupName); 
    419             String groupId; 
    420             try { 
    421                 groupId = groupDir.getUniqueProjection(filter, 
    422                         GroupDirectory.ID_COLUMN); 
    423             } catch (UniqueResultException e) { 
    424                 throw new DirectoryException("group does not exist: " 
    425                         + groupName, e); 
    426             } 
    427  
    428             // get childGroupId 
    429             filter.clear(); 
    430             filter.put(GroupDirectory.GROUP_COLUMN, childGroupName); 
    431             String childGroupId; 
    432             try { 
    433                 childGroupId = groupDir.getUniqueProjection(filter, 
    434                         GroupDirectory.ID_COLUMN); 
    435             } catch (UniqueResultException e) { 
    436                 throw new DirectoryException("group does not exist: " 
    437                         + childGroupName, e); 
    438             } 
    439  
    440312            // create entry in group2group directory 
    441313            HashMap<String, Object> map = new HashMap<String, Object>(); 
    442             map.put(Group2GroupDirectory.PARENT_COLUMN, groupId); 
    443             map.put(Group2GroupDirectory.CHILD_COLUMN, childGroupId); 
     314            map.put(Group2GroupDirectory.PARENT_COLUMN, parentId); 
     315            map.put(Group2GroupDirectory.CHILD_COLUMN, childId); 
    444316            group2groupDir.createEntry(map); 
    445317            group2groupDir.commit(); 
    446318        } finally { 
    447             if (groupDir != null) { 
    448                 groupDir.close(); 
    449             } 
    450319            if (group2groupDir != null) { 
    451320                group2groupDir.close(); 
     
    457326    /* 
    458327     * (non-Javadoc) 
    459      * 
     328     *  
    460329     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#addPrincipalMember(java.lang.String, 
    461330     *      org.nuxeo.ecm.core.api.NuxeoPrincipal) 
    462331     */ 
    463     private void addPrincipalToGroup(String principalName, String groupName
     332    private void addPrincipalToGroup(String principalId, String groupId
    464333            throws ClientException { 
    465334        DirectoryClient user2groupDir = null; 
    466335        DirectoryClient groupDir = null; 
    467336        DirectoryClient userDir = null; 
    468         HashMap<String, Object> filter = new HashMap<String, Object>(); 
    469337        try { 
    470338            userDir = dirInstance.open(UserDirectory.DIRECTORY_NAME); 
     
    474342 
    475343            // check if the group exists 
    476             filter.put(GroupDirectory.GROUP_COLUMN, groupName); 
    477             String groupId; 
    478             try { 
    479                 groupId = groupDir.getUniqueProjection(filter, 
    480                         GroupDirectory.ID_COLUMN); 
    481             } catch (UniqueResultException e) { 
    482                 throw new DirectoryException("group does not exist: " 
    483                         + groupName, e); 
     344            // TODO: add hasEntry method to directories 
     345            // (to avoid having construct the DocumentModel instance) 
     346            DocumentModel group = groupDir.getEntry(groupId); 
     347            if (group == null) { 
     348                throw new DirectoryException("group does not exist: " + groupId); 
    484349            } 
    485350 
    486351            // check if the user exists 
    487             filter.clear(); 
    488             filter.put(UserDirectory.USER_COLUMN, principalName); 
    489             String userId; 
    490             try { 
    491                 userId = userDir.getUniqueProjection(filter, 
    492                         UserDirectory.ID_COLUMN); 
    493             } catch (UniqueResultException e) { 
     352            DocumentModel user = userDir.getEntry(principalId); 
     353            if (user == null) { 
    494354                throw new DirectoryException("user does not exist: " 
    495                         + principalName, e); 
     355                        + principalId); 
    496356            } 
    497357 
    498358            // create entry in user2group 
    499359            HashMap<String, Object> map = new HashMap<String, Object>(); 
    500             map.put(User2GroupDirectory.USERID_COLUMN, userId); 
     360            map.put(User2GroupDirectory.USERID_COLUMN, principalId); 
    501361            map.put(User2GroupDirectory.GROUPID_COLUMN, groupId); 
    502362            user2groupDir.createEntry(map); 
     
    519379    /* 
    520380     * (non-Javadoc) 
    521      * 
     381     *  
    522382     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#createGroup(java.lang.String) 
    523383     */ 
     
    525385        DirectoryClient groupDir = null; 
    526386        try { 
    527             String groupName = group.getName(); 
     387            String groupId = group.getName(); 
    528388            groupDir = dirInstance.open(GroupDirectory.DIRECTORY_NAME); 
    529389 
    530  
    531390            // check the group does not exist 
    532             NuxeoGroup oldGroup = getGroup(groupName); 
    533             if(oldGroup!=null) { 
    534                 throw new DirectoryException("group already exists: " + groupName); 
    535             } 
    536  
     391            NuxeoGroup oldGroup = getGroup(groupId); 
     392            if (oldGroup != null) { 
     393                throw new DirectoryException("group already exists: " + groupId); 
     394            } 
    537395 
    538396            HashMap<String, Object> map = new HashMap<String, Object>(); 
    539             map.put(GroupDirectory.GROUP_COLUMN, groupName); 
     397            // TODO: use idField instead 
     398            map.put(GroupDirectory.GROUP_COLUMN, groupId); 
    540399            groupDir.createEntry(map); 
    541400 
    542             for(String principalName: group.getMemberUsers()) { 
    543                 addPrincipalToGroup(principalName, groupName); 
    544             } 
    545  
    546             for(String childGroupName: group.getMemberGroups()) { 
    547                 addGroupToGroup(childGroupName, groupName); 
     401            for (String principalName : group.getMemberUsers()) { 
     402                addPrincipalToGroup(principalName, groupId); 
     403            } 
     404 
     405            for (String childGroupName : group.getMemberGroups()) { 
     406                addGroupToGroup(childGroupName, groupId); 
    548407            } 
    549408 
     
    554413            } 
    555414        } 
    556  
    557     } 
    558  
    559     /* 
    560      * (non-Javadoc) 
    561      * 
     415    } 
     416 
     417    /* 
     418     * (non-Javadoc) 
     419     *  
    562420     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#createPrincipal(java.lang.String) 
    563421     */ 
     
    569427            String principalName = principal.getName(); 
    570428 
    571             // check the group does not exist 
    572             HashMap<String, Object> filter = new HashMap<String, Object>(); 
    573             filter.put(UserDirectory.USER_COLUMN, principalName); 
    574             List<String> users = userDir.getProjection(filter, 
    575                     UserDirectory.USER_COLUMN); 
    576             if (users.size() != 0) { 
    577                 throw new DirectoryException("User already exists."); 
     429            // check the user does not exist 
     430            // TODO: use hasEntry 
     431            DocumentModel user = userDir.getEntry(principalName); 
     432            if (user != null) { 
     433                throw new DirectoryException("User " + principalName 
     434                        + " already exists."); 
    578435            } 
    579436 
    580437            HashMap<String, Object> map = new HashMap<String, Object>(); 
    581             map.put(UserDirectory.USER_COLUMN, principalName); 
     438            map.put(userDir.getIdField(), principalName); 
    582439            map.put(UserDirectory.FIRSTNAME_COLUMN, principal.getFirstName()); 
    583440            map.put(UserDirectory.LASTNAME_COLUMN, principal.getLastName()); 
    584441            map.put(UserDirectory.COMPANY_COLUMN, principal.getCompany()); 
    585             map.put(UserDirectory.PASSWORD_COLUMN, principal.getPassword()); 
     442            map.put(userDir.getPasswordField(), principal.getPassword()); 
    586443            userDir.createEntry(map); 
    587444 
    588             for(String roleName: principal.getRoles()) { 
     445            for (String roleName : principal.getRoles()) { 
    589446                addPrincipalToRole(principalName, roleName); 
    590447            } 
    591             for(String groupName: principal.getGroups()) { 
     448            for (String groupName : principal.getGroups()) { 
    592449                addPrincipalToGroup(principalName, groupName); 
    593450            } 
     
    603460    /* 
    604461     * (non-Javadoc) 
    605      * 
     462     *  
    606463     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#deleteGroup(java.lang.String) 
    607464     */ 
     
    612469 
    613470        try { 
    614             String groupName = group.getName(); 
     471            String groupId = group.getName(); 
    615472            groupDir = dirInstance.open(GroupDirectory.DIRECTORY_NAME); 
    616473            user2groupDir = dirInstance 
     
    619476                    .open(Group2GroupDirectory.DIRECTORY_NAME); 
    620477 
     478            // remove group from mapping tables 
     479 
     480            // user2group table 
    621481            HashMap<String, Object> filter = new HashMap<String, Object>(); 
    622  
    623             filter.put(GroupDirectory.GROUP_COLUMN, groupName); 
    624             String groupId; 
    625             try { 
    626                 groupId = groupDir.getUniqueProjection(filter, 
    627                         GroupDirectory.ID_COLUMN); 
    628             } catch (UniqueResultException e) { 
    629                 throw new DirectoryException("Group does not exist: " + groupName, 
    630                         e); 
    631             } 
    632  
    633             // remove group from mapping tables 
    634  
    635             // user2group table 
    636             filter.clear(); 
    637482            filter.put(User2GroupDirectory.GROUPID_COLUMN, groupId); 
    638483            DocumentModelList docModelList = user2groupDir.query(filter); 
     
    678523    /* 
    679524     * (non-Javadoc) 
    680      * 
     525     *  
    681526     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#deletePrincipal(org.nuxeo.ecm.core.api.NuxeoPrincipal) 
    682527     */ 
     
    691536            user2groupDir = dirInstance 
    692537                    .open(User2GroupDirectory.DIRECTORY_NAME); 
    693             user2roleDir = dirInstance.open(User2RoleDirectory.DIRECTORY_NAME); 
    694  
     538 
     539            String userId = principal.getName(); 
     540 
     541            // remove user from all groups 
    695542            HashMap<String, Object> filter = new HashMap<String, Object>(); 
    696  
    697             filter.put(UserDirectory.USER_COLUMN, principal.getName()); 
    698             String userId = userDir.getUniqueProjection(filter, 
    699                     UserDirectory.ID_COLUMN); 
    700  
    701             // remove user from all groups 
    702             filter.clear(); 
    703543            filter.put(User2GroupDirectory.USERID_COLUMN, userId); 
    704  
    705544            DocumentModelList userGroups = user2groupDir.query(filter); 
    706545            for (DocumentModel userGroup : userGroups) { 
     
    708547            } 
    709548 
    710             // remove user from all roles 
    711             filter.clear(); 
    712             filter.put(User2RoleDirectory.USERID_COLUMN, userId); 
    713             DocumentModelList userRoles = user2roleDir.query(filter); 
    714             for (DocumentModel userRole : userRoles) { 
    715                 user2roleDir.deleteEntry(userRole); 
    716             } 
    717  
    718549            // remove user 
    719550            DocumentModel docModel = userDir.getEntry(userId); 
     
    738569    /* 
    739570     * (non-Javadoc) 
    740      * 
     571     *  
    741572     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#getAvailableGroups() 
    742573     */ 
     
    745576        try { 
    746577            groupDir = dirInstance.open(GroupDirectory.DIRECTORY_NAME); 
    747             List<String> groupNames = groupDir 
    748                     .getProjection(GroupDirectory.GROUP_COLUMN); 
    749578 
    750579            List<NuxeoGroup> groups = new ArrayList<NuxeoGroup>(); 
    751             for(String groupName: groupNames) { 
    752                 groups.add(getGroup(groupName)); 
     580            for (DocumentModel entry : groupDir.getEntries()) { 
     581                groups.add(getGroup(entry.getId())); 
    753582            } 
    754583            return groups; 
     
    762591    /* 
    763592     * (non-Javadoc) 
    764      * 
     593     *  
    765594     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#getGroupMembers(java.lang.String) 
    766595     */ 
    767     private List<String> getGroupsInGroup(String groupName) throws ClientException { 
     596    private List<String> getGroupsInGroup(String parentId) 
     597            throws ClientException { 
    768598        DirectoryClient groupDir = null; 
    769599        DirectoryClient group2groupDir = null; 
     
    773603                    .open(Group2GroupDirectory.DIRECTORY_NAME); 
    774604 
     605            // TODO: use hasEntry 
     606            if (groupDir.getEntry(parentId) == null) { 
     607                throw new ClientException("no group " + parentId + " found"); 
     608            } 
     609 
    775610            HashMap<String, Object> filter = new HashMap<String, Object>(); 
    776             filter.put(GroupDirectory.GROUP_COLUMN, groupName); 
    777             String groupId = groupDir.getUniqueProjection(filter, 
    778                     GroupDirectory.ID_COLUMN); 
    779  
    780             filter.clear(); 
    781             filter.put(Group2GroupDirectory.PARENT_COLUMN, groupId); 
    782             List<String> memberIds = group2groupDir.getProjection(filter, 
     611            filter.put(Group2GroupDirectory.PARENT_COLUMN, parentId); 
     612            List<String> childrenIds = group2groupDir.getProjection(filter, 
    783613                    Group2GroupDirectory.CHILD_COLUMN); 
    784  
    785             List<String> groupMembers = new ArrayList<String>(); 
    786             for (String memberId : memberIds) { 
    787                 filter.clear(); 
    788                 filter.put(GroupDirectory.ID_COLUMN, memberId); 
    789                 String memberName = groupDir.getUniqueProjection(filter, 
    790                         GroupDirectory.GROUP_COLUMN); 
    791                 groupMembers.add(memberName); 
    792             } 
    793             return groupMembers; 
     614            return childrenIds; 
    794615        } finally { 
    795616            if (groupDir != null) { 
     
    804625    /* 
    805626     * (non-Javadoc) 
    806      * 
     627     *  
    807628     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#getPrincipalMembers(java.lang.String) 
    808629     */ 
    809     private List<String> getPrincipalsInGroup(String groupName) 
    810             throws ClientException { 
    811         DirectoryClient userDir = null; 
    812         DirectoryClient groupDir = null; 
     630    private List<String> getPrincipalsInGroup(String groupId) 
     631            throws ClientException { 
    813632        DirectoryClient user2groupDir = null; 
    814633        try { 
    815             userDir = dirInstance.open(UserDirectory.DIRECTORY_NAME); 
    816             groupDir = dirInstance.open(GroupDirectory.DIRECTORY_NAME); 
    817634            user2groupDir = dirInstance 
    818635                    .open(User2GroupDirectory.DIRECTORY_NAME); 
    819636 
     637            // TODO: check that group.hasEntry(groupId) 
     638 
    820639            HashMap<String, Object> filter = new HashMap<String, Object>(); 
    821             filter.put(GroupDirectory.GROUP_COLUMN, groupName); 
    822             String groupId = groupDir.getUniqueProjection(filter, 
    823                     GroupDirectory.ID_COLUMN); 
    824  
    825             filter.clear(); 
    826640            filter.put(User2GroupDirectory.GROUPID_COLUMN, groupId); 
    827641            List<String> memberIds = user2groupDir.getProjection(filter, 
    828642                    User2GroupDirectory.USERID_COLUMN); 
    829643 
    830             List<String> groupMembers = new ArrayList<String>(); 
    831             for (String memberId : memberIds) { 
    832                 filter.clear(); 
    833                 filter.put(UserDirectory.ID_COLUMN, memberId); 
    834                 String memberName = userDir.getUniqueProjection(filter, 
    835                         UserDirectory.USER_COLUMN); 
    836                 groupMembers.add(memberName); 
    837             } 
    838             return groupMembers; 
    839         } finally { 
    840             if (userDir != null) { 
    841                 userDir.close(); 
    842             } 
    843             if (groupDir != null) { 
    844                 groupDir.close(); 
    845             } 
     644            return memberIds; 
     645        } finally { 
    846646            if (user2groupDir != null) { 
    847647                user2groupDir.close(); 
     
    852652    /* 
    853653     * (non-Javadoc) 
    854      * 
     654     *  
    855655     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#removeGroupMember(java.lang.String, 
    856656     *      java.lang.String) 
    857657     */ 
    858     private void removeGroupFromGroup(String childGroupName, String groupName) 
    859             throws ClientException { 
    860         DirectoryClient groupDir = null; 
     658    private void removeGroupFromGroup(String childId, String parentId) 
     659            throws ClientException { 
    861660        DirectoryClient group2groupDir = null; 
    862         HashMap<String, Object> filter = new HashMap<String, Object>(); 
    863  
    864         try { 
    865             groupDir = dirInstance.open(GroupDirectory.DIRECTORY_NAME); 
     661        try { 
    866662            group2groupDir = dirInstance 
    867663                    .open(Group2GroupDirectory.DIRECTORY_NAME); 
    868664 
    869             filter.put(GroupDirectory.GROUP_COLUMN, groupName); 
    870             String parentGroupId = groupDir.getUniqueProjection(filter, 
    871                     GroupDirectory.ID_COLUMN); 
    872  
    873             filter.clear(); 
    874             filter.put(GroupDirectory.GROUP_COLUMN, childGroupName); 
    875             String childGroupId = groupDir.getUniqueProjection(filter, 
    876                     GroupDirectory.ID_COLUMN); 
    877  
    878             filter.clear(); 
    879             filter.put(Group2GroupDirectory.CHILD_COLUMN, childGroupId); 
    880             filter.put(Group2GroupDirectory.PARENT_COLUMN, parentGroupId); 
     665            HashMap<String, Object> filter = new HashMap<String, Object>(); 
     666            filter.put(Group2GroupDirectory.CHILD_COLUMN, childId); 
     667            filter.put(Group2GroupDirectory.PARENT_COLUMN, parentId); 
    881668            DocumentModelList docModelList = group2groupDir.query(filter); 
    882669 
    883             if (docModelList.size() != 1) { 
    884                 throw new DirectoryException( 
    885                         "none or multiple entries in group2group table"); 
    886             } 
    887  
    888             DocumentModel docModel = docModelList.get(0); 
    889             group2groupDir.deleteEntry(docModel); 
     670            if (docModelList.size() == 0) { 
     671                throw new DirectoryException(childId + "is not a sub group of" 
     672                        + parentId); 
     673            } 
     674 
     675            for (DocumentModel docModel: docModelList) { 
     676                // there should be only result, but in case data was duplicated, 
     677                // clean it now 
     678                group2groupDir.deleteEntry(docModel); 
     679            } 
    890680 
    891681            group2groupDir.commit(); 
    892682        } finally { 
    893             if (groupDir != null) { 
    894                 groupDir.close(); 
    895             } 
    896683            if (group2groupDir != null) { 
    897684                group2groupDir.close(); 
     
    902689    /* 
    903690     * (non-Javadoc) 
    904      * 
     691     *  
    905692     * @see org.nuxeo.ecm.platform.ec.usermanager.UserManager#removePrincipalMember(java.lang.String, 
    906693     *      org.nuxeo.ecm.core.api.NuxeoPrincipal) 
    907694     */ 
    908     private void removePrincipalFromGroup(String principalName, 
    909             String groupName) throws ClientException { 
    910         DirectoryClient groupDir = null; 
     695    private void removePrincipalFromGroup(String principalId, String groupId) 
     696            throws ClientException { 
    911697        DirectoryClient user2groupDir = null; 
    912         DirectoryClient userDir = null; 
    913         HashMap<String, Object> filter = new HashMap<String, Object>(); 
    914  
    915         try { 
    916             userDir = dirInstance.open(UserDirectory.DIRECTORY_NAME); 
    917             groupDir = dirInstance.open(GroupDirectory.DIRECTORY_NAME); 
     698        try { 
    918699            user2groupDir = dirInstance 
    919700                    .open(User2GroupDirectory.DIRECTORY_NAME); 
    920701 
    921             // find groupId 
    922             filter.put(GroupDirectory.GROUP_COLUMN, groupName); 
    923             String groupId = groupDir.getUniqueProjection(filter, 
    924                     GroupDirectory.ID_COLUMN); 
    925  
    926             // find userId 
    927             filter.clear(); 
    928             filter.put(UserDirectory.USER_COLUMN, principalName); 
    929             String userId = userDir.getUniqueProjection(filter, 
    930                     UserDirectory.ID_COLUMN); 
    931  
    932702            // find user2group mappings 
    933             filter.clear(); 
    934             filter.put(User2GroupDirectory.USERID_COLUMN, userId); 
     703            HashMap<String, Object> filter = new HashMap<String, Object>(); 
     704            filter.put(User2GroupDirectory.USERID_COLUMN, principalId); 
    935705            filter.put(User2GroupDirectory.GROUPID_COLUMN, groupId); 
    936706            DocumentModelList docModelList = user2groupDir.query(filter); 
    937707 
    938             if (docModelList.size() != 1) { 
    939                 throw new DirectoryException( 
    940                         "none or multiple entries in group2group table"); 
    941             } 
    942  
    943             DocumentModel docModel = docModelList.get(0); 
    944             user2groupDir.deleteEntry(docModel); 
     708            if (docModelList.size() == 0) { 
     709                throw new DirectoryException(principalId + "is not a member of" 
     710                        + groupId); 
     711            } 
     712            for (DocumentModel docModel: docModelList) { 
     713                // there should be only result, but in case data was duplicated, 
     714                // clean it now 
     715                user2groupDir.deleteEntry(docModel); 
     716            } 
    945717 
    946718            user2groupDir.commit(); 
    947719        } finally { 
    948             if (userDir != null) { 
    949                 userDir.close(); 
    950             } 
    951             if (groupDir != null) { 
    952                 groupDir.close(); 
    953             } 
    954720            if (user2groupDir != null) { 
    955721                user2groupDir.close(); 
     
    960726    private void addPrincipalToRole(String principalName, String roleName) 
    961727            throws ClientException { 
    962         DirectoryClient user2roleDir = null; 
    963         DirectoryClient roleDir = null; 
     728        // XXX: YAGNI 
     729    } 
     730 
     731    private void removePrincipalFromRole(String principalId, String roleId) 
     732            throws ClientException { 
     733        // XXX: YAGNI 
     734    } 
     735 
     736    public List<NuxeoPrincipal> searchPrincipals(String pattern) 
     737            throws ClientException { 
    964738        DirectoryClient userDir = null; 
    965         HashMap<String, Object> filter = new HashMap<String, Object>(); 
    966         try { 
    967             userDir = dirInstance.open(UserDirectory.DIRECTORY_NAME); 
    968             roleDir = dirInstance.open(RoleDirectory.DIRECTORY_NAME); 
    969             user2roleDir = dirInstance.open(User2RoleDirectory.DIRECTORY_NAME); 
    970  
    971             // find roleId 
    972             filter.put(RoleDirectory.ROLE_COLUMN, roleName); 
    973             String roleId; 
    974             try { 
    975                 roleId = roleDir.getUniqueProjection(filter, 
    976                         RoleDirectory.ID_COLUMN); 
    977             } catch (UniqueResultException e) { 
    978                 throw new DirectoryException("role does not exist: " + roleName, e); 
    979             } 
    980  
    981             // check if the user exists 
    982             filter.clear(); 
    983             filter.put(UserDirectory.USER_COLUMN, principalName); 
    984             String userId; 
    985             try { 
    986                 userId = userDir.getUniqueProjection(filter, 
    987                         UserDirectory.ID_COLUMN); 
    988             } catch (UniqueResultException e) { 
    989                 throw new DirectoryException("user does not exist: " 
    990                         + principalName, e); 
    991             } 
    992  
    993             // create entry in user2role 
    994             HashMap<String, Object> map = new HashMap<String, Object>(); 
    995             map.put(User2RoleDirectory.USERID_COLUMN, userId); 
    996             map.put(User2RoleDirectory.ROLEID_COLUMN, roleId); 
    997             user2roleDir.createEntry(map); 
    998             user2roleDir.commit(); 
    999  
    1000         } finally { 
    1001             if (userDir != null) { 
    1002                 userDir.close(); 
    1003             } 
    1004             if (roleDir != null) { 
    1005                 roleDir.close(); 
    1006             } 
    1007             if (user2roleDir != null) { 
    1008                 user2roleDir.close(); 
    1009             } 
    1010         } 
    1011  
    1012     } 
    1013  
    1014  
    1015     private void removePrincipalFromRole(String principalName, String roleName) 
    1016             throws ClientException { 
    1017         DirectoryClient userDir = null; 
    1018         DirectoryClient roleDir = null; 
    1019         DirectoryClient user2roleDir = null; 
    1020         HashMap<String, Object> filter = new HashMap<String, Object>(); 
    1021  
    1022         try { 
    1023             userDir = dirInstance.open(UserDirectory.DIRECTORY_NAME); 
    1024             roleDir = dirInstance.open(RoleDirectory.DIRECTORY_NAME); 
    1025             user2roleDir = dirInstance.open(User2RoleDirectory.DIRECTORY_NAME); 
    1026  
    1027             // get roleId 
    1028             String roleId; 
    1029             try { 
    1030                 filter.clear(); 
    1031                 filter.put(RoleDirectory.ROLE_COLUMN, roleName); 
    1032                 roleId = roleDir.getUniqueProjection(filter, 
    1033                         RoleDirectory.ID_COLUMN); 
    1034             } catch (UniqueResultException e) { 
    1035                 throw new DirectoryException("Role does not exist: " + roleName); 
    1036             } 
    1037  
    1038             // get userId 
    1039             String userId; 
    1040             try { 
    1041                 filter.clear(); 
    1042                 filter.put(UserDirectory.USER_COLUMN, principalName); 
    1043                 userId = userDir.getUniqueProjection(filter, 
    1044                         UserDirectory.ID_COLUMN); 
    1045             } catch (UniqueResultException e) { 
    1046                 throw new DirectoryException("User does not exist: " + roleName); 
    1047             } 
    1048  
    1049             // remove entry from user2role directory 
    1050             filter.clear(); 
    1051             filter.put(User2RoleDirectory.USERID_COLUMN, userId); 
    1052             filter.put(User2RoleDirectory.ROLEID_COLUMN, roleId); 
    1053             DocumentModelList docModelList = user2roleDir.query(filter); 
    1054  
    1055             if (docModelList.size() != 1) { 
    1056                 throw new DirectoryException( 
    1057                         "none or multiple entries in user2role table"); 
    1058             } 
    1059  
    1060             DocumentModel docModel = docModelList.get(0); 
    1061             user2roleDir.deleteEntry(docModel); 
    1062  
    1063             user2roleDir.commit(); 
    1064         } finally { 
    1065             if (userDir != null) { 
    1066                 userDir.close(); 
    1067             } 
    1068             if (roleDir != null) { 
    1069                 roleDir.close(); 
    1070             } 
    1071             if (user2roleDir != null) { 
    1072                 user2roleDir.close(); 
    1073             } 
    1074         } 
    1075  
    1076     } 
    1077  
    1078     public List<NuxeoPrincipal> searchPrincipals(String pattern) 
    1079             throws ClientException { 
    1080         DirectoryClient userDir = null; 
    1081         if(pattern == null) { 
     739        if (pattern == null) { 
    1082740            throw new IllegalArgumentException("pattern cannot be null"); 
    1083741        } 
    1084         if(!pattern.contains("*")) { 
     742        if (!pattern.contains("*")) { 
    1085743            pattern = "*" + pattern + "*"; 
    1086744        } 
     
    1091749            Map<String, Object> filter = new HashMap<String, Object>(); 
    1092750 
    1093             filter.put(UserDirectory.USER_COLUMN, pattern); 
     751            filter.put(userDir.getIdField(), pattern); 
    1094752            List<String> principalNames = userDir.getProjection(filter, 
    1095                     UserDirectory.USER_COLUMN); 
     753                    userDir.getIdField()); 
    1096754            principalSet.addAll(principalNames); 
    1097755 
     
    1099757            filter.put(UserDirectory.FIRSTNAME_COLUMN, pattern); 
    1100758            principalNames = userDir.getProjection(filter, 
    1101                     UserDirectory.USER_COLUMN); 
     759                    userDir.getIdField()); 
    1102760            principalSet.addAll(principalNames); 
    1103761 
     
    1105763            filter.put(UserDirectory.LASTNAME_COLUMN, pattern); 
    1106764            principalNames = userDir.getProjection(filter, 
    1107                     UserDirectory.USER_COLUMN); 
     765                    userDir.getIdField()); 
    1108766            principalSet.addAll(principalNames); 
    1109767 
     
    1127785            Map<String, Object> filter = new HashMap<String, Object>(); 
    1128786            List<String> principalNames = userDir.getProjection(filter, 
    1129                     UserDirectory.USER_COLUMN); 
     787                    userDir.getIdField()); 
    1130788 
    1131789            List<NuxeoPrincipal> principalList = new ArrayList<NuxeoPrincipal>(); 
     
    1140798            } 
    1141799        } 
    1142  
    1143800    } 
    1144801}