Commit 760ab4aa authored by Adrian Damian's avatar Adrian Damian
Browse files

Added support for numeric ID

parent 2794a880
Loading
Loading
Loading
Loading
+56 −20
Original line number Diff line number Diff line
@@ -68,6 +68,20 @@
 */
package ca.nrc.cadc.ac.server.ldap;

import java.security.AccessControlException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.security.auth.x500.X500Principal;

import org.apache.log4j.Logger;

import ca.nrc.cadc.ac.PersonalDetails;
import ca.nrc.cadc.ac.PosixDetails;
import ca.nrc.cadc.ac.User;
@@ -77,7 +91,9 @@ import ca.nrc.cadc.ac.UserNotFoundException;
import ca.nrc.cadc.ac.UserRequest;
import ca.nrc.cadc.auth.AuthenticationUtil;
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.net.TransientException;

import com.unboundid.ldap.sdk.AddRequest;
import com.unboundid.ldap.sdk.Attribute;
import com.unboundid.ldap.sdk.BindRequest;
@@ -100,17 +116,6 @@ import com.unboundid.ldap.sdk.SimpleBindRequest;
import com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl;
import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedRequest;
import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedResult;
import org.apache.log4j.Logger;

import javax.security.auth.x500.X500Principal;
import java.security.AccessControlException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;


public class LdapUserDAO<T extends Principal> extends LdapDAO
@@ -129,6 +134,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
    protected static final String LDAP_ENTRYDN = "entrydn";
    protected static final String LDAP_COMMON_NAME = "cn";
    protected static final String LDAP_DISTINGUISHED_NAME = "distinguishedName";
    protected static final String LDAP_NUMERICID = "numericid";
    protected static final String LADP_USER_PASSWORD = "userPassword";
    protected static final String LDAP_FIRST_NAME = "givenName";
    protected static final String LDAP_LAST_NAME = "sn";
@@ -139,6 +145,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
    protected static final String LDAP_INSTITUTE = "institute";
    protected static final String LDAP_UID = "uid";
    

    private String[] userAttribs = new String[]
            {
                    LDAP_FIRST_NAME, LDAP_LAST_NAME, LDAP_ADDRESS, LDAP_CITY,
@@ -155,6 +162,7 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
        super(config);
        this.userLdapAttrib.put(HttpPrincipal.class, LDAP_UID);
        this.userLdapAttrib.put(X500Principal.class, LDAP_DISTINGUISHED_NAME);
        this.userLdapAttrib.put(NumericPrincipal.class, LDAP_NUMERICID);

        // add the id attributes to user and member attributes
        String[] princs = userLdapAttrib.values()
@@ -350,16 +358,25 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
        try
        {
            // add new user

            DN userX500DN = getUserRequestsDN(user.getUserID().getName());
            List<Attribute> attributes = new ArrayList<Attribute>();
            addAttribute(attributes, LDAP_OBJECT_CLASS, LDAP_INET_ORG_PERSON);
            addAttribute(attributes, LDAP_OBJECT_CLASS, LDAP_CADC_ACCOUNT);
            addAttribute(attributes, LDAP_COMMON_NAME, user.getUserID()
                .getName());
            addAttribute(attributes, LDAP_DISTINGUISHED_NAME, userDN
                .toNormalizedString());
            addAttribute(attributes, LADP_USER_PASSWORD, userRequest
                    .getPassword());

            addAttribute(attributes, LDAP_NUMERICID, 
                    String.valueOf(genNextNumericId()));
            for (Principal princ : user.getIdentities())
            {
                if (princ instanceof X500Principal)
                {
                    addAttribute(attributes, LDAP_DISTINGUISHED_NAME, 
                            princ.getName());
                }
            }
            for (UserDetails details : user.details)
            {
                if (details.getClass() == PersonalDetails.class)
@@ -462,9 +479,15 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
            throw new UserNotFoundException(msg);
        }
        User<T> user = new User<T>(userID);
        user.getIdentities().add(new HttpPrincipal(searchResult.getAttributeValue(
        user.getIdentities().add(new HttpPrincipal(
                searchResult.getAttributeValue(
                       userLdapAttrib.get(HttpPrincipal.class))));

        user.getIdentities().add(new NumericPrincipal(
                searchResult.getAttributeValueAsLong(
                        userLdapAttrib.get(NumericPrincipal.class))));
        user.getIdentities().add(new X500Principal(
                searchResult.getAttributeValue(
                        userLdapAttrib.get(X500Principal.class))));
        String fname = searchResult.getAttributeValue(LDAP_FIRST_NAME);
        String lname = searchResult.getAttributeValue(LDAP_LAST_NAME);
        PersonalDetails personaDetails = new PersonalDetails(fname, lname);
@@ -772,10 +795,9 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
                        "Unsupported principal type " + userID.getClass());
            }

            User<T> user = getUser(userID);
            Filter filter = Filter.createANDFilter(
                    Filter.createEqualityFilter(searchField,
                                                user.getUserID().getName()),
                                                userID.getName()),
                    Filter.createEqualityFilter(LDAP_MEMBEROF, groupID));

            SearchRequest searchRequest =
@@ -972,4 +994,18 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
            LdapDAO.checkLdapResult(code);
        }
    }
    
    /**
     * Method to return a randomly generated user numeric ID. The default 
     * implementation returns a value between 10000 and Integer.MAX_VALUE.
     * @return
     */
    protected int genNextNumericId()
    {
        Random rand = new Random();

        // nextInt is normally exclusive of the top value,
        // so add 1 to make it inclusive
        return rand.nextInt(Integer.MAX_VALUE - 10000) + 10000;
    }
}
+71 −25
Original line number Diff line number Diff line
@@ -68,39 +68,47 @@
 */
package ca.nrc.cadc.ac.server.ldap;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.util.Collection;
import java.util.Random;

import javax.security.auth.Subject;
import javax.security.auth.x500.X500Principal;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.junit.BeforeClass;
import org.junit.Test;

import ca.nrc.cadc.ac.PersonalDetails;
import ca.nrc.cadc.ac.User;
import ca.nrc.cadc.ac.UserDetails;
import ca.nrc.cadc.ac.UserRequest;
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.util.Log4jInit;
import com.unboundid.ldap.sdk.DN;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.junit.BeforeClass;
import org.junit.Test;

import javax.security.auth.Subject;
import javax.security.auth.x500.X500Principal;
import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.util.Collection;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.unboundid.ldap.sdk.DN;

public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest
{
    private static final Logger log = Logger.getLogger(LdapUserDAOTest.class);

    static final String testUserX509DN = "cn=cadcdaotest1,ou=cadc,o=hia,c=ca";
    static int nextUserNumericID = 666;

    static String testUserDN;
    static User<X500Principal> testUser;
    static User<X500Principal> testMember;
    static LdapConfig config;
    static Random ran = new Random(); // source of randomness for numeric ids

    @BeforeClass
    public static void setUpBeforeClass()
@@ -110,17 +118,32 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest

        // get the configuration of the development server from and config files...
        config = getLdapConfig();

        testUser = new User<X500Principal>(new X500Principal(testUserX509DN));
        X500Principal testUserX500Princ = new X500Principal(testUserX509DN);
        testUser = new User<X500Principal>(testUserX500Princ);
        testUser.details.add(new PersonalDetails("CADC", "DAOTest1"));
        testUser.getIdentities().add(new HttpPrincipal("CadcDaoTest1"));
        testUser.getIdentities().add(testUserX500Princ);
        testUser.getIdentities().add(new NumericPrincipal(666));

        testUserDN = "uid=cadcdaotest1," + config.getUsersDN();
        
        
        // member returned by getMember contains only the fields required by
        // the GMS
        testMember = new User<X500Principal>(testUserX500Princ);
        testMember.details.add(new PersonalDetails("CADC", "DAOTest1"));
        testMember.getIdentities().add(new HttpPrincipal("CadcDaoTest1"));
        
    }

    LdapUserDAO getUserDAO()
    {
        return new LdapUserDAO(config);
        return new LdapUserDAO(config){
            protected int genNextNumericId()
            {
                return nextUserNumericID;
            }
        };
    }

    String getUserID()
@@ -134,8 +157,13 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest
    @Test
    public void testAddUser() throws Exception
    {
        final User<HttpPrincipal> expected = new User<HttpPrincipal>(new HttpPrincipal(getUserID()));
        expected.getIdentities().add(new HttpPrincipal(getUserID()));
        String userID = getUserID();
        final User<HttpPrincipal> expected = new User<HttpPrincipal>(new HttpPrincipal(userID));
        expected.getIdentities().add(new HttpPrincipal(userID));
        expected.getIdentities().add(new X500Principal("cn=" + userID + ",ou=cadc,o=hia,c=ca"));
        nextUserNumericID = ran.nextInt(Integer.MAX_VALUE);
        expected.getIdentities().add(new NumericPrincipal(nextUserNumericID));
        
        expected.details.add(new PersonalDetails("foo", "bar"));

        final UserRequest<HttpPrincipal> userRequest =
@@ -265,6 +293,7 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest
        Subject subject = new Subject();
        subject.getPrincipals().add(testUser.getUserID());

        
        // do everything as owner
        Subject.doAs(subject, new PrivilegedExceptionAction<Object>()
        {
@@ -273,7 +302,7 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest
                try
                {
                    User<X500Principal> actual = getUserDAO().getMember(new DN(testUserDN));
                    check(testUser, actual);
                    check(testMember, actual);
                    return null;
                }
                catch (Exception e)
@@ -296,7 +325,7 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest
                try
                {
                    User<X500Principal> actual = getUserDAO().getMember(new DN(testUserDN));
                    check(testUser, actual);
                    check(testMember, actual);
                    return null;
                }
                catch (Exception e)
@@ -490,6 +519,10 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest
        HttpPrincipal principal = new HttpPrincipal(username);
        testUser2 = new User<HttpPrincipal>(principal);
        testUser2.getIdentities().add(principal);
        testUser2.getIdentities().add(new X500Principal("cn=" + username + ",ou=cadc,o=hia,c=ca"));
        // update nextNumericId
        nextUserNumericID = ran.nextInt(Integer.MAX_VALUE);
        testUser2.getIdentities().add(new NumericPrincipal(nextUserNumericID));
        testUser2.details.add(new PersonalDetails("firstName", "lastName"));
        final UserRequest userRequest = new UserRequest(testUser2, password);

@@ -575,7 +608,20 @@ public class LdapUserDAOTest<T extends Principal> extends AbstractLdapDAOTest
        assertEquals(user1, user2);
        assertEquals(user1.details, user2.details);
        assertEquals(user1.details.size(), user2.details.size());
        assertEquals(user1.getIdentities(), user2.getIdentities());
        assertEquals(user1.getIdentities().size(), user2.getIdentities().size());
        for( Principal princ1 : user1.getIdentities())
        {
            boolean found = false;
            for( Principal princ2 : user2.getIdentities())
            {
                if (princ2.getClass() == princ1.getClass())
                {
                    assertEquals(princ1, princ2);
                    found = true;
                }
            }
            assertTrue(princ1.getName(), found);
        }
        for(UserDetails d1 : user1.details)
        {
            assertTrue(user2.details.contains(d1));