Commit 1fd509e1 authored by Brian Major's avatar Brian Major
Browse files

issue-10 - Group Identifiers now represented by GroupURI objects

parent f6757bd1
......@@ -13,7 +13,7 @@ repositories {
sourceCompatibility = 1.7
group = 'org.opencadc'
version = '1.0.2'
version = '1.0.3'
dependencies {
compile 'log4j:log4j:1.2.+'
......@@ -22,7 +22,7 @@ dependencies {
compile 'xerces:xercesImpl:2.+'
compile 'com.unboundid:unboundid-ldapsdk:2.3.+'
compile 'org.opencadc:cadc-access-control:1.+'
compile 'org.opencadc:cadc-access-control:[1.0.2,)'
compile 'org.opencadc:cadc-util:1.+'
compile 'org.opencadc:cadc-log:1.+'
compile 'org.opencadc:cadc-registry:1.+'
......
......@@ -69,6 +69,8 @@
package ca.nrc.cadc.ac.server.ldap;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Collection;
......@@ -79,18 +81,6 @@ import java.util.Set;
import org.apache.log4j.Logger;
import ca.nrc.cadc.ac.ActivatedGroup;
import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.GroupAlreadyExistsException;
import ca.nrc.cadc.ac.GroupNotFoundException;
import ca.nrc.cadc.ac.User;
import ca.nrc.cadc.ac.UserNotFoundException;
import ca.nrc.cadc.ac.server.GroupDetailSelector;
import ca.nrc.cadc.auth.DNPrincipal;
import ca.nrc.cadc.net.TransientException;
import ca.nrc.cadc.profiler.Profiler;
import ca.nrc.cadc.util.StringUtil;
import com.unboundid.ldap.sdk.AddRequest;
import com.unboundid.ldap.sdk.Attribute;
import com.unboundid.ldap.sdk.DN;
......@@ -110,6 +100,21 @@ import com.unboundid.ldap.sdk.SearchResultListener;
import com.unboundid.ldap.sdk.SearchResultReference;
import com.unboundid.ldap.sdk.SearchScope;
import ca.nrc.cadc.ac.ActivatedGroup;
import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.GroupAlreadyExistsException;
import ca.nrc.cadc.ac.GroupNotFoundException;
import ca.nrc.cadc.ac.GroupURI;
import ca.nrc.cadc.ac.User;
import ca.nrc.cadc.ac.UserNotFoundException;
import ca.nrc.cadc.ac.server.GroupDetailSelector;
import ca.nrc.cadc.auth.DNPrincipal;
import ca.nrc.cadc.net.TransientException;
import ca.nrc.cadc.profiler.Profiler;
import ca.nrc.cadc.reg.Standards;
import ca.nrc.cadc.reg.client.LocalAuthority;
import ca.nrc.cadc.util.StringUtil;
public class LdapGroupDAO extends LdapDAO
{
private static final Logger logger = Logger.getLogger(LdapGroupDAO.class);
......@@ -193,16 +198,16 @@ public class LdapGroupDAO extends LdapDAO
else
{
// add group to groups tree
LDAPResult result = addGroup(getGroupDN(group.getID()),
group.getID(), ownerDN,
LDAPResult result = addGroup(getGroupDN(group.getID().getName()),
group.getID().getName(), ownerDN,
group.description,
group.getUserMembers(),
group.getGroupMembers());
LdapDAO.checkLdapResult(result.getResultCode());
// add group to admin groups tree
result = addGroup(getAdminGroupDN(group.getID()),
group.getID(), ownerDN,
result = addGroup(getAdminGroupDN(group.getID().getName()),
group.getID().getName(), ownerDN,
group.description,
group.getUserAdmins(),
group.getGroupAdmins());
......@@ -245,7 +250,7 @@ public class LdapGroupDAO extends LdapDAO
}
for (Group groupMember : groups)
{
final String groupMemberID = groupMember.getID();
final String groupMemberID = groupMember.getID().getName();
if (!checkGroupExists(groupMemberID))
{
throw new GroupNotFoundException(groupMemberID);
......@@ -285,9 +290,9 @@ public class LdapGroupDAO extends LdapDAO
try
{
// check group name exists
Filter filter = Filter.createEqualityFilter(LDAP_CN, group.getID());
Filter filter = Filter.createEqualityFilter(LDAP_CN, group.getID().getName());
DN groupDN = getGroupDN(group.getID());
DN groupDN = getGroupDN(group.getID().getName());
SearchRequest searchRequest =
new SearchRequest(groupDN.toNormalizedString(), SearchScope.BASE,
filter, new String[]{LDAP_NSACCOUNTLOCK});
......@@ -537,7 +542,7 @@ public class LdapGroupDAO extends LdapDAO
throws GroupNotFoundException, TransientException,
AccessControlException, UserNotFoundException
{
String groupID = group.getID();
String groupID = group.getID().getName();
getGroup(getGroupDN(groupID), groupID, PUB_GROUP_ATTRS);//group must exists first
return modifyGroup(group, false);
}
......@@ -580,11 +585,11 @@ public class LdapGroupDAO extends LdapDAO
}
for (Group gr : group.getGroupMembers())
{
if (!checkGroupExists(gr.getID()))
if (!checkGroupExists(gr.getID().getName()))
{
throw new GroupNotFoundException(gr.getID());
throw new GroupNotFoundException(gr.getID().getName());
}
DN grDN = getGroupDN(gr.getID());
DN grDN = getGroupDN(gr.getID().getName());
newMembers.add(grDN.toNormalizedString());
}
......@@ -596,11 +601,11 @@ public class LdapGroupDAO extends LdapDAO
}
for (Group gr : group.getGroupAdmins())
{
if (!checkGroupExists(gr.getID()))
if (!checkGroupExists(gr.getID().getName()))
{
throw new GroupNotFoundException(gr.getID());
throw new GroupNotFoundException(gr.getID().getName());
}
DN grDN = getGroupDN(gr.getID());
DN grDN = getGroupDN(gr.getID().getName());
newAdmins.add(grDN.toNormalizedString());
}
......@@ -610,7 +615,7 @@ public class LdapGroupDAO extends LdapDAO
(String[]) newAdmins.toArray(new String[newAdmins.size()])));
ModifyRequest adminModify =
new ModifyRequest(getAdminGroupDN(group.getID()), adminMods);
new ModifyRequest(getAdminGroupDN(group.getID().getName()), adminMods);
LdapDAO.checkLdapResult(
getReadWriteConnection().modify(adminModify).getResultCode());
......@@ -621,7 +626,7 @@ public class LdapGroupDAO extends LdapDAO
(String[]) newMembers.toArray(new String[newMembers.size()])));
ModifyRequest modifyRequest =
new ModifyRequest(getGroupDN(group.getID()), mods);
new ModifyRequest(getGroupDN(group.getID().getName()), mods);
LdapDAO.checkLdapResult(
getReadWriteConnection().modify(modifyRequest).getResultCode());
......@@ -635,11 +640,11 @@ public class LdapGroupDAO extends LdapDAO
{
if (withActivate)
{
return new ActivatedGroup(getGroup(group.getID(), true));
return new ActivatedGroup(getGroup(group.getID().getName(), true));
}
else
{
return getGroup(group.getID(), true);
return getGroup(group.getID().getName(), true);
}
}
catch (GroupNotFoundException e)
......@@ -748,43 +753,55 @@ public class LdapGroupDAO extends LdapDAO
private Group createGroupFromSearchResult(SearchResultEntry result, String[] attributes)
throws LDAPException, TransientException
{
if (result.getAttribute(LDAP_NSACCOUNTLOCK) != null)
try
{
throw new RuntimeException("BUG: found group with nsaccountlock set: " +
result.getAttributeValue(LDAP_ENTRYDN));
}
if (result.getAttribute(LDAP_NSACCOUNTLOCK) != null)
{
throw new RuntimeException("BUG: found group with nsaccountlock set: " +
result.getAttributeValue(LDAP_ENTRYDN));
}
String entryDN = result.getAttributeValue(LDAP_ENTRYDN);
String groupName = result.getAttributeValue(LDAP_CN);
if (attributes == PUB_GROUP_ATTRS)
{
return new Group(groupName);
}
String entryDN = result.getAttributeValue(LDAP_ENTRYDN);
String groupName = result.getAttributeValue(LDAP_CN);
LocalAuthority localAuthority = new LocalAuthority();
URI gmsServiceID = localAuthority.getServiceURI(Standards.GMS_GROUPS_01.toString());
if (attributes == PUB_GROUP_ATTRS)
{
GroupURI groupID = new GroupURI(gmsServiceID.toString() + "?" + groupName);
return new Group(groupID);
}
String ownerDN = result.getAttributeValue(LDAP_OWNER);
if (ownerDN == null)
{
throw new AccessControlException(groupName);
}
try
{
User owner = userDAO.getUser(new DNPrincipal(ownerDN));
Group group = new Group(groupName);
setField(group, owner, LDAP_OWNER);
if (result.hasAttribute(LDAP_DESCRIPTION))
String ownerDN = result.getAttributeValue(LDAP_OWNER);
if (ownerDN == null)
{
throw new AccessControlException(groupName);
}
try
{
group.description = result.getAttributeValue(LDAP_DESCRIPTION);
User owner = userDAO.getUser(new DNPrincipal(ownerDN));
GroupURI groupID = new GroupURI(gmsServiceID.toString() + "?" + groupName);
Group group = new Group(groupID);
setField(group, owner, LDAP_OWNER);
if (result.hasAttribute(LDAP_DESCRIPTION))
{
group.description = result.getAttributeValue(LDAP_DESCRIPTION);
}
if (result.hasAttribute(LDAP_MODIFY_TIMESTAMP))
{
group.lastModified = result.getAttributeValueAsDate(LDAP_MODIFY_TIMESTAMP);
}
return group;
}
if (result.hasAttribute(LDAP_MODIFY_TIMESTAMP))
catch (UserNotFoundException ex)
{
group.lastModified = result.getAttributeValueAsDate(LDAP_MODIFY_TIMESTAMP);
throw new RuntimeException("Invalid state: owner does not exist: " +
ownerDN + " group: " + entryDN);
}
return group;
}
catch (UserNotFoundException ex)
catch (URISyntaxException e)
{
throw new RuntimeException("Invalid state: owner does not exist: " +
ownerDN + " group: " + entryDN);
logger.error("invalid group URI", e);
throw new IllegalStateException("Invalid group URI", e);
}
}
......
......@@ -223,7 +223,7 @@ public class LdapGroupPersistence extends LdapPersistence implements GroupPersis
AccessControlException, UserNotFoundException
{
Subject callerSubject = AuthenticationUtil.getCurrentSubject();
boolean allowed = isAdmin(callerSubject, group.getID());
boolean allowed = isAdmin(callerSubject, group.getID().getName());
LdapGroupDAO groupDAO = null;
LdapUserDAO userDAO = null;
......@@ -234,7 +234,7 @@ public class LdapGroupPersistence extends LdapPersistence implements GroupPersis
groupDAO = new LdapGroupDAO(conns, userDAO);
if (!allowed)
{
Group g = groupDAO.getGroup(group.getID(), false);
Group g = groupDAO.getGroup(group.getID().getName(), false);
if (isOwner(callerSubject, g))
allowed = true;
}
......@@ -287,13 +287,13 @@ public class LdapGroupPersistence extends LdapPersistence implements GroupPersis
while ( i.hasNext() )
{
Group g = i.next();
if (groupID == null || g.getID().equalsIgnoreCase(groupID))
if (groupID == null || g.getID().getName().equalsIgnoreCase(groupID))
{
if (detailSelector != null && detailSelector.isDetailedSearch(g, role))
{
try
{
Group g2 = groupDAO.getGroup(g.getID(), false);
Group g2 = groupDAO.getGroup(g.getID().getName(), false);
log.debug("role " + role + " loaded: " + g2);
ret.add(g2);
}
......@@ -340,7 +340,7 @@ public class LdapGroupPersistence extends LdapPersistence implements GroupPersis
List<Group> groups = getGroupCache(caller, Role.MEMBER);
for (Group g : groups)
{
if (g.getID().equalsIgnoreCase(groupName))
if (g.getID().getName().equalsIgnoreCase(groupName))
return true;
}
return false;
......@@ -351,7 +351,7 @@ public class LdapGroupPersistence extends LdapPersistence implements GroupPersis
List<Group> groups = getGroupCache(caller, Role.ADMIN);
for (Group g : groups)
{
if (g.getID().equalsIgnoreCase(groupName))
if (g.getID().getName().equalsIgnoreCase(groupName))
return true;
}
return false;
......
......@@ -86,25 +86,6 @@ import javax.security.auth.x500.X500Principal;
import org.apache.log4j.Logger;
import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.InternalID;
import ca.nrc.cadc.ac.PersonalDetails;
import ca.nrc.cadc.ac.Role;
import ca.nrc.cadc.ac.User;
import ca.nrc.cadc.ac.UserAlreadyExistsException;
import ca.nrc.cadc.ac.UserNotFoundException;
import ca.nrc.cadc.ac.UserRequest;
import ca.nrc.cadc.ac.client.GroupMemberships;
import ca.nrc.cadc.auth.DNPrincipal;
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.net.TransientException;
import ca.nrc.cadc.profiler.Profiler;
import ca.nrc.cadc.reg.Standards;
import ca.nrc.cadc.reg.client.LocalAuthority;
import ca.nrc.cadc.util.ObjectUtil;
import ca.nrc.cadc.util.StringUtil;
import com.unboundid.ldap.sdk.AddRequest;
import com.unboundid.ldap.sdk.Attribute;
import com.unboundid.ldap.sdk.BindRequest;
......@@ -129,6 +110,26 @@ import com.unboundid.ldap.sdk.SimpleBindRequest;
import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedRequest;
import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedResult;
import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.GroupURI;
import ca.nrc.cadc.ac.InternalID;
import ca.nrc.cadc.ac.PersonalDetails;
import ca.nrc.cadc.ac.Role;
import ca.nrc.cadc.ac.User;
import ca.nrc.cadc.ac.UserAlreadyExistsException;
import ca.nrc.cadc.ac.UserNotFoundException;
import ca.nrc.cadc.ac.UserRequest;
import ca.nrc.cadc.ac.client.GroupMemberships;
import ca.nrc.cadc.auth.DNPrincipal;
import ca.nrc.cadc.auth.HttpPrincipal;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.net.TransientException;
import ca.nrc.cadc.profiler.Profiler;
import ca.nrc.cadc.reg.Standards;
import ca.nrc.cadc.reg.client.LocalAuthority;
import ca.nrc.cadc.util.ObjectUtil;
import ca.nrc.cadc.util.StringUtil;
/**
*
......@@ -781,11 +782,22 @@ public class LdapUserDAO extends LdapDAO
// some pretty horrible hacks to avoid querying LDAP for group details...
private Group createGroupFromDN(DN groupDN)
{
LocalAuthority localAuthority = new LocalAuthority();
URI gmsServiceURI = localAuthority.getServiceURI(Standards.GMS_GROUPS_01.toString());
String cn = groupDN.getRDNString();
String[] parts = cn.split("=");
if (parts.length == 2 && parts[0].equals("cn"))
{
return new Group(parts[1]);
try
{
GroupURI groupID = new GroupURI(gmsServiceURI.toString() + "?" + parts[1]);
return new Group(groupID);
}
catch (URISyntaxException e)
{
logger.error("Illegal Group ID", e);
throw new IllegalStateException("Illegal Group ID", e);
}
}
throw new RuntimeException("BUG: failed to extract group name from " + groupDN
.toString());
......
......@@ -68,12 +68,16 @@
*/
package ca.nrc.cadc.ac.server.web.groups;
import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.GroupAlreadyExistsException;
import ca.nrc.cadc.ac.server.GroupPersistence;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.GroupAlreadyExistsException;
import ca.nrc.cadc.ac.GroupURI;
import ca.nrc.cadc.reg.Standards;
import ca.nrc.cadc.reg.client.LocalAuthority;
public class AddGroupMemberAction extends AbstractGroupAction
{
private final String groupName;
......@@ -90,7 +94,10 @@ public class AddGroupMemberAction extends AbstractGroupAction
public void doAction() throws Exception
{
Group group = groupPersistence.getGroup(this.groupName);
Group toAdd = new Group(this.groupMemberName);
LocalAuthority localAuthority = new LocalAuthority();
URI gmsServiceURI = localAuthority.getServiceURI(Standards.GMS_GROUPS_01.toString());
GroupURI toAddID = new GroupURI(gmsServiceURI.toString() + "?" + this.groupMemberName);
Group toAdd = new Group(toAddID);
if (!group.getGroupMembers().add(toAdd))
{
throw new GroupAlreadyExistsException(this.groupMemberName);
......@@ -98,8 +105,8 @@ public class AddGroupMemberAction extends AbstractGroupAction
groupPersistence.modifyGroup(group);
List<String> addedMembers = new ArrayList<String>();
addedMembers.add(toAdd.getID());
logGroupInfo(group.getID(), null, addedMembers);
addedMembers.add(toAdd.getID().getName());
logGroupInfo(group.getID().getName(), null, addedMembers);
}
}
......@@ -113,7 +113,7 @@ public class AddUserMemberAction extends AbstractGroupAction
List<String> addedMembers = new ArrayList<String>();
addedMembers.add(getUseridForLogging(toAdd));
logGroupInfo(group.getID(), null, addedMembers);
logGroupInfo(group.getID().getName(), null, addedMembers);
}
}
......@@ -104,7 +104,7 @@ public class CreateGroupAction extends AbstractGroupAction
addedMembers = new ArrayList<String>();
for (Group gr : group.getGroupMembers())
{
addedMembers.add(gr.getID());
addedMembers.add(gr.getID().getName());
}
for (User usr : group.getUserMembers())
{
......@@ -116,7 +116,7 @@ public class CreateGroupAction extends AbstractGroupAction
addedMembers.add(p.getName());
}
}
logGroupInfo(group.getID(), null, addedMembers);
logGroupInfo(group.getID().getName(), null, addedMembers);
}
}
......@@ -92,7 +92,7 @@ public class DeleteGroupAction extends AbstractGroupAction
this.logInfo.deletedMembers = new ArrayList<String>();
for (Group gr : deletedGroup.getGroupMembers())
{
this.logInfo.deletedMembers.add(gr.getID());
this.logInfo.deletedMembers.add(gr.getID().getName());
}
for (User usr : deletedGroup.getUserMembers())
{
......
......@@ -114,7 +114,7 @@ public class ModifyGroupAction extends AbstractGroupAction
{
if (!oldGroup.getGroupMembers().remove(gr))
{
addedMembers.add(gr.getID());
addedMembers.add(gr.getID().getName());
}
}
if (addedMembers.isEmpty())
......@@ -128,13 +128,13 @@ public class ModifyGroupAction extends AbstractGroupAction
}
for (Group gr : oldGroup.getGroupMembers())
{
deletedMembers.add(gr.getID());
deletedMembers.add(gr.getID().getName());
}
if (deletedMembers.isEmpty())
{
deletedMembers = null;
}
logGroupInfo(group.getID(), deletedMembers, addedMembers);
logGroupInfo(group.getID().getName(), deletedMembers, addedMembers);
profiler.checkpoint("log GroupInfo");
syncOut.setHeader("Location", request);
......
......@@ -68,14 +68,22 @@
*/
package ca.nrc.cadc.ac.server.web.groups;
import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.GroupNotFoundException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.GroupNotFoundException;
import ca.nrc.cadc.ac.GroupURI;
import ca.nrc.cadc.reg.Standards;
import ca.nrc.cadc.reg.client.LocalAuthority;
public class RemoveGroupMemberAction extends AbstractGroupAction
{
private final static Logger log = Logger.getLogger(RemoveGroupMemberAction.class);
private final String groupName;
private final String groupMemberName;
......@@ -89,7 +97,13 @@ public class RemoveGroupMemberAction extends AbstractGroupAction
public void doAction() throws Exception
{
Group group = groupPersistence.getGroup(this.groupName);
Group toRemove = new Group(this.groupMemberName);
LocalAuthority localAuthority = new LocalAuthority();
URI gmsServiceURI = localAuthority.getServiceURI(Standards.GMS_GROUPS_01.toString());
GroupURI toRemoveID = new GroupURI(gmsServiceURI.toString() + "?" + this.groupMemberName);
Group toRemove = new Group(toRemoveID);
log.debug("group member count: " + group.getGroupMembers().size());
log.debug("contains one to remove: " + group.getGroupMembers().contains(toRemove));
if (!group.getGroupMembers().remove(toRemove))
{
......@@ -98,8 +112,8 @@ public class RemoveGroupMemberAction extends AbstractGroupAction
groupPersistence.modifyGroup(group);
List<String> deletedMembers = new ArrayList<String>();
deletedMembers.add(toRemove.getID());
logGroupInfo(group.getID(), deletedMembers, null);
deletedMembers.add(toRemove.getID().getName());
logGroupInfo(group.getID().getName(), deletedMembers, null);
}
}
......@@ -110,7 +110,7 @@ public class RemoveUserMemberAction extends AbstractGroupAction
List<String> deletedMembers = new ArrayList<String>();
deletedMembers.add(getUseridForLogging(user));
logGroupInfo(group.getID(), deletedMembers, null);
logGroupInfo(group.getID().getName(), deletedMembers, null);
}
protected UserPersistence getUserPersistence()
......
......@@ -87,6 +87,7 @@ import org.junit.Test;
import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.GroupNotFoundException;
import ca.nrc.cadc.ac.GroupProperty;