Skip to content

Commit

Permalink
add groupsFor(AuthenticatedUser au) method #3055
Browse files Browse the repository at this point in the history
  • Loading branch information
pdurbin committed Apr 5, 2016
1 parent 90cb6da commit ea89841
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,12 @@ private String getDvObjectIdListClause(List<Long> dvObjectIdList){
}
return " AND r.definitionpoint_id IN (" + StringUtils.join(outputList, ",") + ")";
}


private List<String> getUserGroups(String roleAssigneeIdentifier){

/**
* @todo Support groups within groups:
* https://github.com/IQSS/dataverse/issues/3056
*/
public List<String> getUserGroups(String roleAssigneeIdentifier) {

String qstr = "select groupalias from explicitgroup";
qstr += " where id in ";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import edu.harvard.iq.dataverse.authorization.groups.impl.ipaddress.IpGroupsServiceBean;
import edu.harvard.iq.dataverse.authorization.groups.impl.shib.ShibGroupProvider;
import edu.harvard.iq.dataverse.authorization.groups.impl.shib.ShibGroupServiceBean;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import java.util.HashMap;
import java.util.HashSet;
Expand Down Expand Up @@ -102,6 +103,41 @@ public Set<Group> groupsFor( RoleAssignee ra, DvObject dvo ) {
return groupTransitiveClosure(groups, dvo);
}

/**
* groupsFor( RoleAssignee ra, DvObject dvo ) doesn't really get *all* the
* groups a Role assignee belongs to as advertised but this method comes
* closer.
*
* @todo Determine if this method works with IP Groups.
*
* @param au An AuthenticatedUser.
* @return As many groups as we can find for the AuthenticatedUser.
*/
public Set<Group> groupsFor(AuthenticatedUser au) {
Set<Group> groups = new HashSet<>();
groups.addAll(groupsFor(au, null));
String identifier = au.getIdentifier();
String identifierWithoutAtSign = null;
if (identifier != null) {
try {
identifierWithoutAtSign = identifier.substring(1);
} catch (IndexOutOfBoundsException ex) {
logger.info("Couldn't trim first character (@ sign) from identifier: " + identifier);
}
}
if (identifierWithoutAtSign != null) {
roleAssigneeSvc.getUserGroups(identifierWithoutAtSign).stream().forEach((groupAlias) -> {
ExplicitGroup explicitGroup = explicitGroupProvider.get(groupAlias);
if (explicitGroup != null) {
groups.add(explicitGroup);
} else {
logger.info("Couldn't find group based on alias " + groupAlias);
}
});
}
return groups;
}

/**
* Given a set of groups and a DV object, return all the groups that are
* reachable from the set. Effectively, if the initial set has an {@link ExplicitGroup},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -818,48 +818,28 @@ private String getPermissionFilterQuery(User user, SolrQuery solrQuery, Datavers
// * @todo add onlyDatatRelatedToMe option into the experimental JOIN
// * before enabling it.
// */
String groupsFromProviders = "";
/**
* @todo What should the value be? Is null ok? From a search
* perspective, we don't care about if the group was created within one
* dataverse or another. We just want a list of all the groups the user
* is part of. A JOIN on "permission documents" will determine if the
* user can find a given "content document" (dataset version, etc) in
* Solr.
*/
// DvObject groupsForDvObjectParamNull = null;
// Set<Group> groups = groupService.groupsFor(au, groupsForDvObjectParamNull);
/**
* @todo What is the expected behavior when you pass in a dataverse? It
* seems like no matter what you pass in you always get the following
* types of groups:
*
* - BuiltIn Groups
* From a search perspective, we don't care about if the group was
* created within one dataverse or another. We just want a list of *all*
* the groups the user is part of. We are greedy. We want all BuiltIn
* Groups, Shibboleth Groups, IP Groups, "system" groups, everything.
*
* - IP Groups
*
* - Shibboleth Groups
*
* If you pass in the root dataverse it seems like you get all groups
* that you're part of.
*
* If you pass in a non-root dataverse, it seems like you get groups
* that you're part of for that dataverse. It's unclear if there is any
* inheritance of groups.
* A JOIN on "permission documents" will determine if the user can find
* a given "content document" (dataset version, etc) in Solr.
*/
DvObject groupsForDvObjectParamCurrentDataverse = dataverse;
Set<Group> groups = groupService.groupsFor(au, groupsForDvObjectParamCurrentDataverse);
String groupsFromProviders = "";
Set<Group> groups = groupService.groupsFor(au);
StringBuilder sb = new StringBuilder();
for (Group group : groups) {
logger.fine("found group " + group.getIdentifier() + " with alias " + group.getAlias());
String groupAlias = group.getAlias();
if (groupAlias != null && !groupAlias.isEmpty()) {
sb.append(" OR ");
// i.e. group_shib/2
// i.e. group_builtIn/all-users, group_builtIn/authenticated-users, group_1-explictGroup1, group_shib/2
sb.append(IndexServiceBean.getGroupPrefix() + groupAlias);
}
groupsFromProviders = sb.toString();
}
groupsFromProviders = sb.toString();

logger.fine(groupsFromProviders);
if (true) {
Expand Down
86 changes: 85 additions & 1 deletion src/test/java/edu/harvard/iq/dataverse/api/SearchIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,90 @@ public void testAssignRoleAtDataset() throws InterruptedException {

}

@Test
public void testAssignGroupAtDataverse() throws InterruptedException {
Response createUser1 = UtilIT.createRandomUser();
String username1 = UtilIT.getUsernameFromResponse(createUser1);
String apiToken1 = UtilIT.getApiTokenFromResponse(createUser1);

Response createDataverse1Response = UtilIT.createRandomDataverse(apiToken1);
createDataverse1Response.prettyPrint();
assertEquals(201, createDataverse1Response.getStatusCode());
String dvAlias = UtilIT.getAliasFromResponse(createDataverse1Response);
int dvId = JsonPath.from(createDataverse1Response.asString()).getInt("data.id");

Response createDataset1Response = UtilIT.createRandomDatasetViaNativeApi(dvAlias, apiToken1);
createDataset1Response.prettyPrint();
assertEquals(201, createDataset1Response.getStatusCode());
Integer datasetId1 = UtilIT.getDatasetIdFromResponse(createDataset1Response);

Response createUser2 = UtilIT.createRandomUser();
createUser2.prettyPrint();
String username2 = UtilIT.getUsernameFromResponse(createUser2);
String apiToken2 = UtilIT.getApiTokenFromResponse(createUser2);

String aliasInOwner = "groupFor" + dvAlias;
String displayName = "Group for " + dvAlias;
String user2identifier = "@" + username2;
Response createGroup = UtilIT.createGroup(dvAlias, aliasInOwner, displayName, apiToken1);
createGroup.prettyPrint();
String groupIdentifier = JsonPath.from(createGroup.asString()).getString("data.identifier");

assertEquals(201, createGroup.getStatusCode());
List<String> roleAssigneesToAdd = new ArrayList<>();
roleAssigneesToAdd.add(user2identifier);
Response addToGroup = UtilIT.addToGroup(dvAlias, aliasInOwner, roleAssigneesToAdd, apiToken1);
addToGroup.prettyPrint();

Response grantRoleResponse = UtilIT.grantRoleOnDataverse(dvAlias, "admin", groupIdentifier, apiToken1);
grantRoleResponse.prettyPrint();

assertEquals(200, grantRoleResponse.getStatusCode());
sleep(500l);
Response shouldBeVisible = querySolr("id:dataset_" + datasetId1 + "_draft_permission");
shouldBeVisible.prettyPrint();
String discoverableBy = JsonPath.from(shouldBeVisible.asString()).getString("response.docs.discoverableBy");

Set actual = new HashSet<>();
for (String userOrGroup : discoverableBy.replaceAll("\\[", "").replaceAll("\\]", "").replaceAll(" ", "").split(",")) {
actual.add(userOrGroup);
}

Set expected = new HashSet<>();
createUser1.prettyPrint();
String userid1 = JsonPath.from(createUser1.asString()).getString("data.user.id");
expected.add("group_user" + userid1);
expected.add("group_" + dvId + "-" + aliasInOwner);
logger.info("expected: " + expected);
logger.info("actual: " + actual);
assertEquals(expected, actual);

Response enableNonPublicSearch = enableSetting(SettingsServiceBean.Key.SearchApiNonPublicAllowed);
assertEquals(200, enableNonPublicSearch.getStatusCode());

TestSearchQuery query = new TestSearchQuery("*");

JsonObjectBuilder createdUser = Json.createObjectBuilder();
createdUser.add(idKey, Integer.MAX_VALUE);
createdUser.add(usernameKey, username2);
createdUser.add(apiTokenKey, apiToken2);
JsonObject json = createdUser.build();

TestUser testUser = new TestUser(json);
Response searchResponse = search(query, testUser);

searchResponse.prettyPrint();
Set<String> titles = new HashSet<>(JsonPath.from(searchResponse.asString()).getList("data.items.name"));
System.out.println("title: " + titles);
Set expectedNames = new HashSet<>();
expectedNames.add(dvAlias);
expectedNames.add("Darwin's Finches");
assertEquals(expectedNames, titles);

Response disableNonPublicSearch = deleteSetting(SettingsServiceBean.Key.SearchApiNonPublicAllowed);
assertEquals(200, disableNonPublicSearch.getStatusCode());
}

@Test
public void homerPublishesVersion2AfterDeletingFile() throws InterruptedException {
if (homerPublishesVersion2AfterDeletingFile) {
Expand Down Expand Up @@ -780,7 +864,7 @@ private Response grantRole(String definitionPoint, String role, String roleAssig
JsonObjectBuilder roleBuilder = Json.createObjectBuilder();
roleBuilder.add("assignee", "@" + roleAssignee);
roleBuilder.add("role", role);
JsonObject roleObject = roleBuilder.build();
String roleObject = roleBuilder.build().toString();
System.out.println("Granting role on dataverse alias \"" + definitionPoint + "\": " + roleObject);
return given()
.body(roleObject).contentType(ContentType.JSON)
Expand Down
38 changes: 38 additions & 0 deletions src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.junit.Test;
import static com.jayway.restassured.RestAssured.given;
import static com.jayway.restassured.path.xml.XmlPath.from;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
Expand Down Expand Up @@ -320,6 +321,43 @@ private static String getTitleFromSwordStatement(String swordStatement) {
return new XmlPath(swordStatement).getString("feed.title");
}

static Response createGroup(String dataverseToCreateGroupIn, String aliasInOwner, String displayName, String apiToken) {
JsonObjectBuilder groupBuilder = Json.createObjectBuilder();
groupBuilder.add("aliasInOwner", aliasInOwner);
groupBuilder.add("displayName", displayName);
Response response = given()
.header(API_TOKEN_HTTP_HEADER, apiToken)
.body(groupBuilder.build().toString())
.contentType(ContentType.JSON)
.post("/api/dataverses/" + dataverseToCreateGroupIn + "/groups");
return response;
}

static Response addToGroup(String dataverseThatGroupBelongsIn, String groupIdentifier, List<String> roleAssigneesToAdd, String apiToken) {
JsonArrayBuilder groupBuilder = Json.createArrayBuilder();
roleAssigneesToAdd.stream().forEach((string) -> {
groupBuilder.add(string);
});
Response response = given()
.header(API_TOKEN_HTTP_HEADER, apiToken)
.body(groupBuilder.build().toString())
.contentType(ContentType.JSON)
.post("/api/dataverses/" + dataverseThatGroupBelongsIn + "/groups/" + groupIdentifier + "/roleAssignees");
return response;
}

static public Response grantRoleOnDataverse(String definitionPoint, String role, String roleAssignee, String apiToken) {
JsonObjectBuilder roleBuilder = Json.createObjectBuilder();
roleBuilder.add("assignee", roleAssignee);
roleBuilder.add("role", role);
JsonObject roleObject = roleBuilder.build();
logger.info("Granting role on dataverse alias \"" + definitionPoint + "\": " + roleObject);
return given()
.body(roleObject.toString())
.contentType(ContentType.JSON)
.post("api/dataverses/" + definitionPoint + "/assignments?key=" + apiToken);
}

public static Response deleteUser(String username) {
Response deleteUserResponse = given()
.delete("/api/admin/authenticatedUsers/" + username + "/");
Expand Down

0 comments on commit ea89841

Please sign in to comment.