REPO-556: List People - Allow people to be retrieved via the /people collection

- added implementation for get people endpoint
   - added tests

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@132343 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Raluca Munteanu
2016-11-03 15:34:33 +00:00
parent 8e553ec442
commit bb0296b851
4 changed files with 301 additions and 62 deletions

View File

@@ -26,6 +26,8 @@
package org.alfresco.rest.api; package org.alfresco.rest.api;
import org.alfresco.rest.api.model.Person; import org.alfresco.rest.api.model.Person;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.NoSuchPersonException; import org.alfresco.service.cmr.security.NoSuchPersonException;
@@ -33,6 +35,10 @@ public interface People
{ {
String DEFAULT_USER = "-me-"; String DEFAULT_USER = "-me-";
String PARAM_FIRST_NAME = "firstName";
String PARAM_LAST_NAME = "lastName";
String PARAM_USER_NAME = "userName";
String validatePerson(String personId); String validatePerson(String personId);
String validatePerson(String personId, boolean validateIsCurrentUser); String validatePerson(String personId, boolean validateIsCurrentUser);
NodeRef getAvatar(String personId); NodeRef getAvatar(String personId);
@@ -59,4 +65,11 @@ public interface People
* @return The updated person details. * @return The updated person details.
*/ */
Person update(String personId, Person person); Person update(String personId, Person person);
/**
* Get people list
*
* @return CollectionWithPagingInfo<Person>
*/
CollectionWithPagingInfo<Person> getPeople(Parameters parameters);
} }

View File

@@ -25,7 +25,17 @@
*/ */
package org.alfresco.rest.api.impl; package org.alfresco.rest.api.impl;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.query.PagingRequest;
import org.alfresco.query.PagingResults;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.Nodes;
@@ -35,8 +45,17 @@ import org.alfresco.rest.api.model.Person;
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException; import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.rest.framework.resource.parameters.Parameters; import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.cmr.repository.*; import org.alfresco.rest.framework.resource.parameters.SortColumn;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.NoSuchPersonException; import org.alfresco.service.cmr.security.NoSuchPersonException;
@@ -45,11 +64,7 @@ import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.cmr.thumbnail.ThumbnailService; import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.service.cmr.usage.ContentUsageService; import org.alfresco.service.cmr.usage.ContentUsageService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/** /**
* Centralises access to people services and maps between representations. * Centralises access to people services and maps between representations.
@@ -70,6 +85,16 @@ public class PeopleImpl implements People
protected ContentService contentService; protected ContentService contentService;
protected ThumbnailService thumbnailService; protected ThumbnailService thumbnailService;
private final static Map<String, QName> sort_params_to_qnames;
static
{
Map<String, QName> aMap = new HashMap<>(3);
aMap.put(PARAM_FIRST_NAME, ContentModel.PROP_FIRSTNAME);
aMap.put(PARAM_LAST_NAME, ContentModel.PROP_LASTNAME);
aMap.put(PARAM_USER_NAME, ContentModel.PROP_USERNAME);
sort_params_to_qnames = Collections.unmodifiableMap(aMap);
}
public void setSites(Sites sites) public void setSites(Sites sites)
{ {
this.sites = sites; this.sites = sites;
@@ -236,47 +261,112 @@ public class PeopleImpl implements People
/** /**
* *
* @throws NoSuchPersonException if personId does not exist * @throws NoSuchPersonException
* if personId does not exist
*/ */
public Person getPerson(String personId) public Person getPerson(String personId)
{ {
Person person = null; personId = validatePerson(personId);
Person person = getPersonWithProperties(personId);
personId = validatePerson(personId); return person;
NodeRef personNode = personService.getPerson(personId, false); }
if (personNode != null)
{
Map<QName, Serializable> nodeProps = nodeService.getProperties(personNode);
processPersonProperties(nodeProps);
// TODO this needs to be run as admin but should we do this here?
final String pId = personId;
Boolean enabled = AuthenticationUtil.runAsSystem(new RunAsWork<Boolean>()
{
public Boolean doWork() throws Exception
{
return authenticationService.getAuthenticationEnabled(pId);
}
});
person = new Person(personNode, nodeProps, enabled);
// get avatar information public CollectionWithPagingInfo<Person> getPeople(final Parameters parameters)
if(hasAvatar(personNode)) {
{ Paging paging = parameters.getPaging();
try PagingRequest pagingRequest = Util.getPagingRequest(paging);
{
NodeRef avatar = getAvatar(personId); List<Pair<QName, Boolean>> sortProps = getSortProps(parameters);
person.setAvatarId(avatar);
} // For now the results are not filtered
catch(EntityNotFoundException e) // please see REPO-555
{ final PagingResults<PersonService.PersonInfo> pagingResult = personService.getPeople(null, null, sortProps, pagingRequest);
// shouldn't happen, but ok
} final List<PersonService.PersonInfo> page = pagingResult.getPage();
} int totalItems = pagingResult.getTotalResultCount().getFirst();
} final String personId = AuthenticationUtil.getFullyAuthenticatedUser();
else List<Person> people = new AbstractList<Person>()
{ {
throw new EntityNotFoundException(personId); @Override
} public Person get(int index)
{
PersonService.PersonInfo personInfo = page.get(index);
Person person = getPersonWithProperties(personInfo.getUserName());
return person;
}
@Override
public int size()
{
return page.size();
}
};
return CollectionWithPagingInfo.asPaged(paging, people, pagingResult.hasMoreItems(), totalItems);
}
private List<Pair<QName, Boolean>> getSortProps(Parameters parameters)
{
List<Pair<QName, Boolean>> sortProps = new ArrayList<>();
List<SortColumn> sortCols = parameters.getSorting();
if ((sortCols != null) && (sortCols.size() > 0))
{
for (SortColumn sortCol : sortCols)
{
QName sortPropQName = sort_params_to_qnames.get(sortCol.column);
if (sortPropQName == null)
{
throw new InvalidArgumentException("Invalid sort field: " + sortCol.column);
}
sortProps.add(new Pair<>(sortPropQName, (sortCol.asc ? Boolean.TRUE : Boolean.FALSE)));
}
}
else
{
// default sort order
sortProps.add(new Pair<>(ContentModel.PROP_USERNAME, Boolean.TRUE));
}
return sortProps;
}
private Person getPersonWithProperties(String personId)
{
Person person = null;
NodeRef personNode = personService.getPerson(personId, false);
if (personNode != null)
{
Map<QName, Serializable> nodeProps = nodeService.getProperties(personNode);
processPersonProperties(nodeProps);
// TODO this needs to be run as admin but should we do this here?
final String pId = personId;
Boolean enabled = AuthenticationUtil.runAsSystem(new RunAsWork<Boolean>()
{
public Boolean doWork() throws Exception
{
return authenticationService.getAuthenticationEnabled(pId);
}
});
person = new Person(personNode, nodeProps, enabled);
// get avatar information
if (hasAvatar(personNode))
{
try
{
NodeRef avatar = getAvatar(personId);
person.setAvatarId(avatar);
}
catch (EntityNotFoundException e)
{
// shouldn't happen, but ok
}
}
}
else
{
throw new EntityNotFoundException(personId);
}
return person; return person;
} }

View File

@@ -33,6 +33,7 @@ import org.alfresco.rest.framework.core.ResourceParameter;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.resource.EntityResource; import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters; import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@@ -49,7 +50,7 @@ import java.util.List;
* @author Gethin James * @author Gethin James
*/ */
@EntityResource(name="people", title = "People") @EntityResource(name="people", title = "People")
public class PeopleEntityResource implements EntityResourceAction.ReadById<Person>, EntityResourceAction.Create<Person>, EntityResourceAction.Update<Person>, InitializingBean public class PeopleEntityResource implements EntityResourceAction.ReadById<Person>, EntityResourceAction.Create<Person>, EntityResourceAction.Update<Person>,EntityResourceAction.Read<Person>, InitializingBean
{ {
private static Log logger = LogFactory.getLog(PeopleEntityResource.class); private static Log logger = LogFactory.getLog(PeopleEntityResource.class);
@@ -175,4 +176,11 @@ public class PeopleEntityResource implements EntityResourceAction.ReadById<Perso
throw new InvalidArgumentException("Unsupported field: quotaUsed"); throw new InvalidArgumentException("Unsupported field: quotaUsed");
} }
} }
@Override
@WebApiDescription(title = "Get List of People", description = "Get List of People")
public CollectionWithPagingInfo<Person> readAll(Parameters params)
{
return people.getPeople(params);
}
} }

View File

@@ -25,9 +25,22 @@
*/ */
package org.alfresco.rest.api.tests; package org.alfresco.rest.api.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.alfresco.rest.api.tests.RepoService.TestNetwork; import org.alfresco.rest.api.tests.RepoService.TestNetwork;
import org.alfresco.rest.api.tests.client.HttpResponse; import org.alfresco.rest.api.tests.client.HttpResponse;
import org.alfresco.rest.api.tests.client.Pair; import org.alfresco.rest.api.tests.client.Pair;
import org.alfresco.rest.api.tests.client.PublicApiClient;
import org.alfresco.rest.api.tests.client.PublicApiClient.People; import org.alfresco.rest.api.tests.client.PublicApiClient.People;
import org.alfresco.rest.api.tests.client.PublicApiException; import org.alfresco.rest.api.tests.client.PublicApiException;
import org.alfresco.rest.api.tests.client.RequestContext; import org.alfresco.rest.api.tests.client.RequestContext;
@@ -40,30 +53,24 @@ import org.json.simple.JSONObject;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
public class TestPeople extends EnterpriseTestApi public class TestPeople extends EnterpriseTestApi
{ {
private People people; private People people;
private Iterator<TestNetwork> accountsIt; private Iterator<TestNetwork> accountsIt;
private TestNetwork account1; private TestNetwork account1;
private TestNetwork account2; private TestNetwork account2;
private TestNetwork account3; private TestNetwork account3;
private Iterator<String> account1PersonIt; private TestNetwork account4;
private Iterator<String> account2PersonIt; private Iterator<String> account1PersonIt;
private Iterator<String> account2PersonIt;
private Iterator<String> account3PersonIt; private Iterator<String> account3PersonIt;
private String account1Admin; private Iterator<String> account4PersonIt;
private String account2Admin; private String account1Admin;
private String account2Admin;
private String account3Admin; private String account3Admin;
private String account4Admin;
private Person personAlice;
private Person personBen;
@Before @Before
public void setUp() throws Exception public void setUp() throws Exception
@@ -73,9 +80,11 @@ public class TestPeople extends EnterpriseTestApi
account1 = accountsIt.next(); account1 = accountsIt.next();
account2 = accountsIt.next(); account2 = accountsIt.next();
account3 = createNetwork("account3"); account3 = createNetwork("account3");
account4 = createNetwork("account4");
account1Admin = "admin@" + account1.getId(); account1Admin = "admin@" + account1.getId();
account2Admin = "admin@" + account2.getId(); account2Admin = "admin@" + account2.getId();
account3Admin = "admin@" + account3.getId(); account3Admin = "admin@" + account3.getId();
account4Admin = "admin@" + account4.getId();
account1PersonIt = account1.getPersonIds().iterator(); account1PersonIt = account1.getPersonIds().iterator();
account2PersonIt = account2.getPersonIds().iterator(); account2PersonIt = account2.getPersonIds().iterator();
@@ -694,4 +703,123 @@ public class TestPeople extends EnterpriseTestApi
"Expected 400 response when updating " + personId, 400); "Expected 400 response when updating " + personId, 400);
} }
} }
private PublicApiClient.ListResponse<Person> listPeople(final PublicApiClient.Paging paging, String sortColumn, boolean asc) throws Exception
{
final PublicApiClient.People peopleProxy = publicApiClient.people();
// sort params
final Map<String, String> params = new HashMap<>();
if (sortColumn != null)
{
params.put("orderBy", sortColumn + " " + (asc ? "ASC" : "DESC"));
}
return peopleProxy.getPeople(createParams(paging, params));
}
/**
* Tests the capability to sort and paginate the list of people orderBy =
* firstName ASC skip = 1, count = 2
*
* @throws Exception
*/
@Test
public void testPagingAndSortingByFirstNameAsc() throws Exception
{
initializeContextForGetPeople();
// paging
int skipCount = 1;
int maxItems = 2;
int totalResults = 4;
PublicApiClient.Paging paging = getPaging(skipCount, maxItems, totalResults, totalResults);
// orderBy=firstName ASC
PublicApiClient.ListResponse<Person> resp = listPeople(paging, "firstName", true);
List<Person> expectedList = new LinkedList<>();
expectedList.add(personAlice);
expectedList.add(personBen);
checkList(expectedList, paging.getExpectedPaging(), resp);
}
/**
* Tests the capability to sort and paginate the list of people orderBy =
* firstName DESC skip = 1, count = 2
*
* @throws Exception
*/
@Test
public void testPagingAndSortingByFirstNameDesc() throws Exception
{
initializeContextForGetPeople();
// paging
int skipCount = 1;
int maxItems = 2;
int totalResults = 4;
PublicApiClient.Paging paging = getPaging(skipCount, maxItems, totalResults, totalResults);
// orderBy=firstName DESC
PublicApiClient.ListResponse<Person> resp = listPeople(paging, "firstName", false);
List<Person> expectedList = new LinkedList<>();
expectedList.add((Person) personBen);
expectedList.add((Person) personAlice);
checkList(expectedList, paging.getExpectedPaging(), resp);
}
/**
* Tests the capability to sort and paginate the list of people verifies
* default sorting, skip = 1, count = 2
*
* @throws Exception
*/
@Test
public void testPagingAndDefaultSorting() throws Exception
{
initializeContextForGetPeople();
// paging
int skipCount = 1;
int maxItems = 2;
int totalResults = 4;
PublicApiClient.Paging paging = getPaging(skipCount, maxItems, totalResults, totalResults);
// orderBy=firstName DESC
PublicApiClient.ListResponse<Person> resp = listPeople(paging, null, false);
List<Person> expectedList = new LinkedList<>();
expectedList.add((Person) personAlice);
expectedList.add((Person) personBen);
checkList(expectedList, paging.getExpectedPaging(), resp);
}
private void initializeContextForGetPeople() throws PublicApiException
{
publicApiClient.setRequestContext(new RequestContext(account4.getId(), account4Admin, "admin"));
personAlice = new Person();
personAlice.setUserName("alice@" + account4.getId());
personAlice.setId("alice@" + account4.getId());
personAlice.setFirstName("Alice");
personAlice.setLastName("Smith");
personAlice.setEmail("alison.smith@example.com");
personAlice.setPassword("password");
personAlice.setEnabled(true);
people.create(personAlice);
personBen = new Person();
personBen.setUserName("ben@" + account4.getId());
personBen.setId("ben@" + account4.getId());
personBen.setFirstName("Ben");
personBen.setLastName("Smythe");
personBen.setEmail("ben.smythe@example.com");
personBen.setPassword("password");
personBen.setEnabled(true);
people.create(personBen);
}
} }