Commit 54e650f7 authored by Dustin Jenkins's avatar Dustin Jenkins
Browse files

Story 1848: Rework for JSON and fix removing Administrators.

parent 70c7ea2b
Loading
Loading
Loading
Loading
+191 −122
Original line number Diff line number Diff line
@@ -123,11 +123,13 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
            };
    private static final String[] GROUP_ATTRS = new String[]
            {
        "entrydn", "cn", "nsaccountlock", "owner", "modifytimestamp", "description"
                    "entrydn", "cn", "nsaccountlock", "owner",
                    "modifytimestamp", "description"
            };
    private static final String[] GROUP_AND_MEMBER_ATTRS = new String[]
            {
        "entrydn", "cn", "nsaccountlock", "owner", "modifytimestamp", "description", "uniquemember"
                    "entrydn", "cn", "nsaccountlock", "owner",
                    "modifytimestamp", "description", "uniquemember"
            };

    private Profiler profiler = new Profiler(LdapDAO.class);
@@ -152,9 +154,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
     * Persists a group.
     *
     * @param group The group to create
     *
     * @return created group
     *
     * @throws GroupAlreadyExistsException If a group with the same ID already
     *                                     exists.
     * @throws TransientException          If an temporary, unexpected problem occurred.
@@ -263,7 +263,9 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
        if (!members.isEmpty())
        {
            attributes.add(new Attribute("uniquemember",
                (String[]) members.toArray(new String[members.size()])));
                                         (String[]) members
                                                 .toArray(new String[members
                                                         .size()])));
        }

        AddRequest addRequest = new AddRequest(groupDN, attributes);
@@ -278,6 +280,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO

    /**
     * Checks whether group name available for the user or already in use.
     *
     * @param group
     * @return activated group or null if group does not exists
     * @throws AccessControlException
@@ -302,9 +305,11 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO

            searchRequest.addControl(
                    new ProxiedAuthorizationV2RequestControl("dn:" +
                            getSubjectDN().toNormalizedString()));
                                                             getSubjectDN()
                                                                     .toNormalizedString()));

            SearchResultEntry searchResult = getReadWriteConnection().searchForEntry(searchRequest);
            SearchResultEntry searchResult = getReadWriteConnection()
                    .searchForEntry(searchRequest);

            if (searchResult == null)
            {
@@ -313,7 +318,8 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO

            if (searchResult.getAttributeValue("nsaccountlock") == null)
            {
                throw new GroupAlreadyExistsException("Group already exists " + group.getID());
                throw new GroupAlreadyExistsException("Group already exists " + group
                        .getID());
            }

            // activate group
@@ -341,7 +347,6 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
     * Get all group names.
     *
     * @return A collection of strings
     *
     * @throws TransientException If an temporary, unexpected problem occurred.
     */
    public Collection<String> getGroupNames()
@@ -349,7 +354,8 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
    {
        try
        {
            Filter filter = Filter.createNOTFilter(Filter.createPresenceFilter("nsaccountlock"));
            Filter filter = Filter
                    .createNOTFilter(Filter.createPresenceFilter("nsaccountlock"));
            filter = Filter.createANDFilter(filter, Filter.create("(cn=*)"));

            final List<String> groupNames = new LinkedList<String>();
@@ -373,7 +379,8 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
                            if ((groupNames.size() % 100) == 0)
                            {

                                logger.debug("found: " + groupNames.size() + " " + dt + "ms");
                                logger.debug("found: " + groupNames
                                        .size() + " " + dt + "ms");
                                t1 = t2;
                            }
                        }
@@ -382,7 +389,8 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
                        {
                            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                        }
                    }, config.getGroupsDN(), SearchScope.ONE, filter, PUB_GROUP_ATTRS);
                    }, config
                            .getGroupsDN(), SearchScope.ONE, filter, PUB_GROUP_ATTRS);

            SearchResult searchResult = null;
            try
@@ -413,7 +421,8 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
        {
            logger.debug("getGroupNames Exception: " + e1, e1);
            LdapDAO.checkLdapResult(e1.getResultCode());
            throw new IllegalStateException("Unexpected exception: " + e1.getMatchedDN(), e1);
            throw new IllegalStateException("Unexpected exception: " + e1
                    .getMatchedDN(), e1);
        }
    }

@@ -422,9 +431,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
     * Get the group with members.
     *
     * @param groupID The Group unique ID.
     *
     * @return A Group instance
     *
     * @throws GroupNotFoundException If the group was not found.
     * @throws TransientException     If an temporary, unexpected problem occurred.
     */
@@ -450,11 +457,15 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
        logger.debug("getGroup: " + groupDN + " attrs: " + attributes.length);
        String loggableGroupID = xgroupID;
        if (loggableGroupID == null)
            loggableGroupID = groupDN.toString(); // member or admin group: same name, internal tree
        {
            loggableGroupID = groupDN
                    .toString(); // member or admin group: same name, internal tree
        }

        try
        {
            Filter filter = Filter.createNOTFilter(Filter.createPresenceFilter("nsaccountlock"));
            Filter filter = Filter
                    .createNOTFilter(Filter.createPresenceFilter("nsaccountlock"));

            SearchRequest searchRequest =
                    new SearchRequest(groupDN.toNormalizedString(),
@@ -462,10 +473,12 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO

            searchRequest.addControl(
                    new ProxiedAuthorizationV2RequestControl("dn:" +
                            getSubjectDN().toNormalizedString()));
                                                             getSubjectDN()
                                                                     .toNormalizedString()));


            SearchResultEntry searchEntry = getReadOnlyConnection().searchForEntry(searchRequest);
            SearchResultEntry searchEntry = getReadOnlyConnection()
                    .searchForEntry(searchRequest);

            if (searchEntry == null)
            {
@@ -478,7 +491,8 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO

            if (searchEntry.getAttributeValues("uniquemember") != null)
            {
                for (String member : searchEntry.getAttributeValues("uniquemember"))
                for (String member : searchEntry
                        .getAttributeValues("uniquemember"))
                {
                    DN memberDN = new DN(member);
                    if (memberDN.isDescendantOf(config.getUsersDN(), false))
@@ -495,11 +509,13 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
                            // from groups they belong to
                        }
                    }
                    else if (memberDN.isDescendantOf(config.getGroupsDN(), false))
                    else if (memberDN
                            .isDescendantOf(config.getGroupsDN(), false))
                    {
                        try
                        {
                            ldapGroup.getGroupMembers().add(getGroup(memberDN, null, PUB_GROUP_ATTRS));
                            ldapGroup.getGroupMembers()
                                    .add(getGroup(memberDN, null, PUB_GROUP_ATTRS));
                        }
                        catch (GroupNotFoundException e)
                        {
@@ -529,9 +545,7 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
     * Modify the given group.
     *
     * @param group The group to update. It must be an existing group
     *
     * @return The newly updated group.
     *
     * @throws GroupNotFoundException If the group was not found.
     * @throws TransientException     If an temporary, unexpected problem occurred.
     * @throws AccessControlException If the operation is not permitted.
@@ -562,18 +576,21 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
        if (withActivate)
        {
            mods.add(new Modification(ModificationType.DELETE, "nsaccountlock"));
            adminMods.add(new Modification(ModificationType.DELETE, "nsaccountlock"));
            adminMods
                    .add(new Modification(ModificationType.DELETE, "nsaccountlock"));
            adminChanges = true;
        }

        if (group.description == null)
        if (StringUtil.hasText(group.description))
        {
            mods.add(new Modification(ModificationType.REPLACE, "description"));
            mods.add(new Modification(ModificationType.REPLACE, "description",
                                      group.description));
        }
        else
        {
            mods.add(new Modification(ModificationType.REPLACE, "description", group.description));
            mods.add(new Modification(ModificationType.REPLACE, "description"));
        }

        try
        {
            Set<String> newMembers = new HashSet<String>();
@@ -598,6 +615,15 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
            {
                existingUserAdmins = existing.getUserAdmins();
            }

            // All the user administrators may have been removed.
            // account for that.
            if (group.getUserAdmins().isEmpty())
            {
                adminChanges = true;
            }
            else
            {
                for (User<?> member : group.getUserAdmins())
                {
                    DN memberDN = userPersist.getUserDN(member);
@@ -607,12 +633,22 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
                        adminChanges = true;
                    }
                }
            }

            Set<Group> existingGroupAdmins = new HashSet<Group>(0);
            if (existing != null)
            {
                existingGroupAdmins = existing.getGroupAdmins();
            }

            // All the group administrators may have been removed.
            // account for that.
            if (group.getGroupAdmins().isEmpty())
            {
                adminChanges = true;
            }
            else
            {
                for (Group gr : group.getGroupAdmins())
                {
                    if (!checkGroupExists(gr.getID()))
@@ -627,11 +663,17 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
                        adminChanges = true;
                    }
                }
            }

            mods.add(new Modification(ModificationType.REPLACE, "uniquemember",
                    (String[]) newMembers.toArray(new String[newMembers.size()])));
            adminMods.add(new Modification(ModificationType.REPLACE, "uniquemember",
                    (String[]) newAdmins.toArray(new String[newAdmins.size()])));
                                      (String[]) newMembers
                                              .toArray(new String[newMembers
                                                      .size()])));
            adminMods
                    .add(new Modification(ModificationType.REPLACE, "uniquemember",
                                          (String[]) newAdmins
                                                  .toArray(new String[newAdmins
                                                          .size()])));

            // modify admin group first (if necessary)
            if (adminChanges)
@@ -642,7 +684,9 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
                        new ProxiedAuthorizationV2RequestControl(
                                "dn:" + getSubjectDN().toNormalizedString()));

                LdapDAO.checkLdapResult(getReadWriteConnection().modify(modifyRequest).getResultCode());
                LdapDAO.checkLdapResult(getReadWriteConnection()
                                                .modify(modifyRequest)
                                                .getResultCode());
            }

            // modify the group itself now
@@ -652,7 +696,9 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
                    new ProxiedAuthorizationV2RequestControl(
                            "dn:" + getSubjectDN().toNormalizedString()));

            LdapDAO.checkLdapResult(getReadWriteConnection().modify(modifyRequest).getResultCode());
            LdapDAO.checkLdapResult(getReadWriteConnection()
                                            .modify(modifyRequest)
                                            .getResultCode());
        }
        catch (LDAPException e1)
        {
@@ -672,7 +718,8 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
        }
        catch (GroupNotFoundException e)
        {
            throw new RuntimeException("BUG: modified group not found (" + group.getID() + ")");
            throw new RuntimeException("BUG: modified group not found (" + group
                    .getID() + ")");
        }
    }

@@ -680,7 +727,6 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
     * Deletes the group.
     *
     * @param groupID The group to delete
     *
     * @throws GroupNotFoundException If the group was not found.
     * @throws TransientException     If an temporary, unexpected problem occurred.
     */
@@ -736,9 +782,12 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
        try
        {
            getGroup(getGroupDN(group.getID()), null, GROUP_ATTRS);
            throw new RuntimeException("BUG: group not deleted " + group.getID());
            throw new RuntimeException("BUG: group not deleted " + group
                    .getID());
        }
        catch (GroupNotFoundException ignore)
        {
        }
        catch (GroupNotFoundException ignore) { }
    }

    /**
@@ -748,7 +797,6 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
     * @param userID  The userID.
     * @param role    Role of the user, either owner, member, or read/write.
     * @param groupID The Group ID.
     *
     * @return possibly empty collection of Group that match the query
     * @throws TransientException     If an temporary, unexpected problem occurred.
     * @throws UserNotFoundException
@@ -789,7 +837,9 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
                groupDNs = getMemberGroups(user, userDN, groupID, true);
            }
            else
            {
                throw new IllegalArgumentException("null role");
            }

            ret = new ArrayList<Group>();
            try
@@ -798,7 +848,8 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
                {
                    if (role == Role.ADMIN)
                    {
                        groupDN = new DN(groupDN.getRDNString() + "," + config.getGroupsDN());
                        groupDN = new DN(groupDN.getRDNString() + "," + config
                                .getGroupsDN());
                    }
                    try
                    {
@@ -825,7 +876,8 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
            }
        }

        logger.debug("found: " + ret.size() + "groups matching " + userID + "," + role + "," + groupID);
        logger.debug("found: " + ret
                .size() + "groups matching " + userID + "," + role + "," + groupID);
        return ret;
    }

@@ -838,14 +890,17 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
        {
            return new Group(parts[1]);
        }
        throw new RuntimeException("BUG: failed to extract group name from " + groupDN.toString());
        throw new RuntimeException("BUG: failed to extract group name from " + groupDN
                .toString());
    }


    private boolean isDetailedSearch(Group g, Role r)
    {
        if (searchDetailSelector == null)
        {
            return true;
        }
        return searchDetailSelector.isDetailedSearch(g, r);
    }
    // end of horribleness
@@ -858,16 +913,19 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
        Collection<Group> ret = new ArrayList<Group>();
        try
        {
            Filter filter = Filter.createNOTFilter(Filter.createPresenceFilter("nsaccountlock"));
            Filter filter = Filter
                    .createNOTFilter(Filter.createPresenceFilter("nsaccountlock"));

            filter = Filter.createANDFilter(filter,
                Filter.createEqualityFilter("owner", userDN.toNormalizedString()));
                                            Filter.createEqualityFilter("owner", userDN
                                                    .toNormalizedString()));

            if (groupID != null)
            {
                DN groupDN = getGroupDN(groupID);
                filter = Filter.createANDFilter(filter,
                    Filter.createEqualityFilter("entrydn", groupDN.toNormalizedString()));
                                                Filter.createEqualityFilter("entrydn", groupDN
                                                        .toNormalizedString()));
            }

            SearchRequest searchRequest = new SearchRequest(
@@ -875,9 +933,11 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO

            searchRequest.addControl(
                    new ProxiedAuthorizationV2RequestControl("dn:" +
                            getSubjectDN().toNormalizedString()));
                                                             getSubjectDN()
                                                                     .toNormalizedString()));

            SearchResult results = getReadOnlyConnection().search(searchRequest);
            SearchResult results = getReadOnlyConnection()
                    .search(searchRequest);
            for (SearchResultEntry result : results.getSearchEntries())
            {
                ret.add(createGroupFromEntry(result, GROUP_ATTRS));
@@ -896,25 +956,35 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
    {
        if (result.getAttribute("nsaccountlock") != null)
        {
            throw new RuntimeException("BUG: found group with nsaccountlock set: " + result.getAttributeValue("entrydn").toString());
            throw new RuntimeException("BUG: found group with nsaccountlock set: " + result
                    .getAttributeValue("entrydn").toString());
        }

        String entryDN = result.getAttributeValue("entrydn");
        String groupName = result.getAttributeValue("cn");
        if (attributes == PUB_GROUP_ATTRS)
        {
            return new Group(groupName);
        }

        DN ownerDN = result.getAttributeValueAsDN("owner");
        if (ownerDN == null)
        {
            throw new AccessControlException(groupName);
        }
        try
        {
            User owner = userPersist.getX500User(ownerDN);
            Group g = new Group(groupName, owner);
            if (result.hasAttribute("description"))
            {
                g.description = result.getAttributeValue("description");
            }
            if (result.hasAttribute("modifytimestamp"))
                g.lastModified = result.getAttributeValueAsDate("modifytimestamp");
            {
                g.lastModified = result
                        .getAttributeValueAsDate("modifytimestamp");
            }
            return g;
        }
        catch (UserNotFoundException ex)
@@ -958,7 +1028,6 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
    }

    /**
     *
     * @param groupID
     * @return
     */
@@ -977,7 +1046,6 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
    }

    /**
     *
     * @param groupID
     * @return
     */
@@ -996,7 +1064,6 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
    }

    /**
     *
     * @param owner
     * @return
     * @throws UserNotFoundException
@@ -1035,7 +1102,9 @@ public class LdapGroupDAO<T extends Principal> extends LdapDAO
        {
            return false;
        }
        finally { }
        finally
        {
        }
    }

}
+9 −2
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ import java.util.Set;
import javax.security.auth.x500.X500Principal;

import ca.nrc.cadc.auth.DNPrincipal;
import ca.nrc.cadc.util.StringUtil;
import com.unboundid.ldap.sdk.ModifyDNRequest;
import org.apache.log4j.Logger;

@@ -662,8 +663,14 @@ public class LdapUserDAO<T extends Principal> extends LdapDAO
                    next.getAttributeValue(LDAP_LAST_NAME).trim();
                final String uid = next.getAttributeValue(LDAP_UID).trim();
                User<Principal> user = new User<Principal>(new HttpPrincipal(uid));
                PersonalDetails pd = new PersonalDetails(firstName, lastName);
                user.details.add(pd);

                // Only add Personal Details if it is relevant.
                if (StringUtil.hasLength(firstName)
                    && StringUtil.hasLength(lastName))
                {
                    user.details.add(new PersonalDetails(firstName, lastName));
                }

                users.add(user);
            }
        }
+17 −7
Original line number Diff line number Diff line
@@ -85,18 +85,28 @@ public class JsonUserListReaderWriterTest

        for (int i = 0; i < 4; i++)
        {
            users.add(new User<HttpPrincipal>(
                    new HttpPrincipal(Integer.toString(i))));
            final User<HttpPrincipal> user = new User<HttpPrincipal>(
                    new HttpPrincipal(Integer.toString(i)));

            user.details.add(new PersonalDetails(Integer.toString(i),
                                                 "NUMBER_"));

            if ((i % 2) == 0)
            {
                user.details.add(new PosixDetails(88l + i, 88l + i, "/tmp"));
            }

            users.add(user);
        }

        testSubject.write(users, writer);

        final JSONObject expected =
                new JSONObject("{\"users\":{\"user\":[{\"userID\":" +
                               "{\"identity\":{\"$\":\"0\",\"@type\":\"HTTP\"}}}," +
                               "{\"userID\":{\"identity\":{\"$\":\"1\",\"@type\":\"HTTP\"}}}," +
                               "{\"userID\":{\"identity\":{\"$\":\"2\",\"@type\":\"HTTP\"}}}," +
                               "{\"userID\":{\"identity\":{\"$\":\"3\",\"@type\":\"HTTP\"}}}]}}");
                new JSONObject("{\"users\":{\"user\":[" +
                               "{\"details\":{\"userDetails\":[{\"firstName\":{\"$\":\"0\"},\"lastName\":{\"$\":\"NUMBER_\"},\"@type\":\"personalDetails\"},{\"uid\":{\"$\":\"88\"},\"gid\":{\"$\":\"88\"},\"homeDirectory\":{\"$\":\"/tmp\"},\"@type\":\"posixDetails\"}]},\"userID\":{\"identity\":{\"$\":\"0\",\"@type\":\"HTTP\"}}}," +
                               "{\"details\":{\"userDetails\":{\"firstName\":{\"$\":\"1\"},\"lastName\":{\"$\":\"NUMBER_\"},\"@type\":\"personalDetails\"}},\"userID\":{\"identity\":{\"$\":\"1\",\"@type\":\"HTTP\"}}}," +
                               "{\"details\":{\"userDetails\":[{\"uid\":{\"$\":\"90\"},\"gid\":{\"$\":\"90\"},\"homeDirectory\":{\"$\":\"/tmp\"},\"@type\":\"posixDetails\"},{\"firstName\":{\"$\":\"2\"},\"lastName\":{\"$\":\"NUMBER_\"},\"@type\":\"personalDetails\"}]},\"userID\":{\"identity\":{\"$\":\"2\",\"@type\":\"HTTP\"}}}," +
                               "{\"details\":{\"userDetails\":{\"firstName\":{\"$\":\"3\"},\"lastName\":{\"$\":\"NUMBER_\"},\"@type\":\"personalDetails\"}},\"userID\":{\"identity\":{\"$\":\"3\",\"@type\":\"HTTP\"}}}]}}");
        final JSONObject result = new JSONObject(writer.toString());

        JSONAssert.assertEquals(expected, result, true);