aspectNames = person.getAspectNames();
assertEquals(2, aspectNames.size());
assertTrue(aspectNames.contains("papi:lunchable"));
assertTrue(aspectNames.contains("papi:comms"));
assertEquals(2, person.getProperties().size());
assertEquals("another@jabber.example.com", person.getProperties().get("papi:jabber"));
assertEquals("sandwich", person.getProperties().get("papi:lunch"));
}
// Remove a property by setting it to null
{
Person person = createTestUpdatePerson();
assertEquals(2, person.getAspectNames().size());
assertTrue(person.getAspectNames().contains("papi:comms"));
assertTrue(person.getAspectNames().contains("papi:dessertable"));
assertEquals(1, person.getProperties().size());
assertTrue(person.getProperties().containsKey("papi:jabber"));
person = people.update(person.getId(), qjson("{`properties`: {`papi:jabber`: null}}"), 200);
// No properties == null
assertNull(person.getProperties());
// The aspect will still be there, I don't think we can easily remove the aspect automatically
// just because the associated properties have all been removed.
assertEquals(2, person.getAspectNames().size());
assertTrue(person.getAspectNames().contains("papi:comms"));
assertTrue(person.getAspectNames().contains("papi:dessertable"));
}
// Cannot set built-in/non-custom props
{
Person person = createTestUpdatePerson();
final String personId = person.getId();
assertEquals(2, person.getAspectNames().size());
assertTrue(person.getAspectNames().contains("papi:comms"));
assertTrue(person.getAspectNames().contains("papi:dessertable"));
String json = qjson("{ `properties`: {`usr:enabled`: false} }");
people.update(person.getId(), json, 400);
json = qjson("{ `properties`: {`cm:title`: `hello-world`} }");
people.update(person.getId(), json, 400);
json = qjson("{ `properties`: {`sys:locale`: `en_GB`} }");
people.update(person.getId(), json, 400);
// Get the person's NodeRef
AuthenticationUtil.setFullyAuthenticatedUser("admin@"+account1.getId());
NodeRef nodeRef = personService.getPerson(person.getId(), false);
// Aspects from non-custom models should still be present.
nodeService.hasAspect(nodeRef, ContentModel.ASPECT_AUDITABLE);
nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TITLED);
// Custom aspects should be undisturbed
person = people.getPerson(personId);
assertEquals(2, person.getAspectNames().size());
assertTrue(person.getAspectNames().contains("papi:comms"));
assertTrue(person.getAspectNames().contains("papi:dessertable"));
assertEquals("jbloggs@example.com", person.getProperties().get("papi:jabber"));
}
}
/**
* Simple helper to make JSON literals a little easier to read in test code,
* by allowing values that would normally be quoted with double quotes, to be
* quoted with backticks instead.
*
* Double and single quotes may still be used as normal, if required.
*
* @param raw The untreated JSON string to munge
* @return JSON String with backticks replaced with double quotes.
*/
private String qjson(String raw)
{
return raw.replace("`", "\"");
}
public static class PersonJSONSerializer implements JSONAble
{
private final Person personUpdate;
public PersonJSONSerializer(Person personUpdate)
{
this.personUpdate = personUpdate;
}
@Override
public JSONObject toJSON()
{
JSONObject personJson = new JSONObject();
if (personUpdate.getUserName() != null)
{
personJson.put("id", personUpdate.getUserName());
}
personJson.put("firstName", personUpdate.getFirstName());
personJson.put("lastName", personUpdate.getLastName());
personJson.put("description", personUpdate.getDescription());
personJson.put("email", personUpdate.getEmail());
personJson.put("skypeId", personUpdate.getSkypeId());
personJson.put("googleId", personUpdate.getGoogleId());
personJson.put("instantMessageId", personUpdate.getInstantMessageId());
personJson.put("jobTitle", personUpdate.getJobTitle());
personJson.put("location", personUpdate.getLocation());
org.alfresco.rest.api.model.Company co = personUpdate.getCompany();
if (co == null)
{
co = new org.alfresco.rest.api.model.Company();
}
personJson.put("company", new Company(co).toJSON());
personJson.put("mobile", personUpdate.getMobile());
personJson.put("telephone", personUpdate.getTelephone());
personJson.put("userStatus", personUpdate.getUserStatus());
personJson.put("enabled", personUpdate.isEnabled());
personJson.put("emailNotificationsEnabled", personUpdate.isEmailNotificationsEnabled());
personJson.put("password", personUpdate.getPassword());
personJson.put("properties", personUpdate.getProperties());
personJson.put("aspectNames", personUpdate.getAspectNames());
return personJson;
}
}
@Test
public void testUpdatePersonAuthenticationFailed() throws PublicApiException
{
final String personId = account2PersonIt.next();
publicApiClient.setRequestContext(new RequestContext(account1.getId(), personId));
people.update("people", personId, null, null, "{\n" + " \"firstName\": \"Updated firstName\"\n" + "}", null, "Expected 401 response when updating " + personId, 401);
}
@Test
public void testUpdatePersonNonSelfAndNonAdminDisallowed() throws PublicApiException
{
// TODO: this is bad, it seems that the test fixture isn't unique per test!?
final String personId = account1PersonIt.next();
final String personToUpdateId = account1PersonIt.next();
publicApiClient.setRequestContext(new RequestContext(account1.getId(), personId));
people.update(personToUpdateId, qjson("{ `firstName`:`Updated firstName` }"), 403);
// TODO: temp fix, set back to orig firstName
publicApiClient.setRequestContext(new RequestContext(account1.getId(), account1Admin, "admin"));
people.update(personToUpdateId, qjson("{ `firstName`:`Bob` }"), 200);
}
@Test
public void testUpdatePersonCanUpdateThemself() throws PublicApiException
{
final String personId = account1PersonIt.next();
publicApiClient.setRequestContext(new RequestContext(account1.getId(), personId));
// Explicitly using the person's ID
{
Person updatedPerson = people.update(personId, qjson("{ `firstName`: `Matt` }"), 200);
assertEquals("Matt", updatedPerson.getFirstName());
}
// "-me-" user
{
Person updatedPerson = people.update("-me-", qjson("{ `firstName`: `John` }"), 200);
assertEquals("John", updatedPerson.getFirstName());
}
// TODO: temp fix, set back to orig firstName
publicApiClient.setRequestContext(new RequestContext(account1.getId(), account1Admin, "admin"));
people.update(personId, qjson("{ `firstName`:`Bill` }"), 200);
// -ve test: check that required/mandatory/non-null fields cannot be unset (or empty string)
{
people.update("people", personId, null, null, qjson("{ `firstName`:`` }"), null, "Expected 400 response when updating " + personId, 400);
people.update("people", personId, null, null, qjson("{ `email`:`` }"), null, "Expected 400 response when updating " + personId, 400);
people.update("people", personId, null, null, qjson("{ `emailNotificationsEnabled`:`` }"), null, "Expected 400 response when updating " + personId, 400);
}
}
@Test
public void testUpdatePersonNonexistentPerson() throws PublicApiException
{
final String personId = "non-existent";
publicApiClient.setRequestContext(new RequestContext(account3.getId(), account3Admin, "admin"));
people.update("people", personId, null, null, "{\n" + " \"firstName\": \"Updated firstName\"\n" + "}", null, "Expected 404 response when updating " + personId, 404);
}
@Test
public void testUpdatePersonUsingPartialUpdate() throws PublicApiException
{
final String personId = account3.createUser().getId();
publicApiClient.setRequestContext(new RequestContext(account3.getId(), account3Admin, "admin"));
String updatedFirstName = "Updated firstName";
HttpResponse response = people.update("people", personId, null, null, "{\n" + " \"firstName\": \"" + updatedFirstName + "\"\n" + "}", null,
"Expected 200 response when updating " + personId, 200);
Person updatedPerson = Person.parsePerson((JSONObject) response.getJsonResponse().get("entry"));
assertEquals(updatedFirstName, updatedPerson.getFirstName());
}
@Test
public void testUpdatePersonWithRestrictedResponseFields() throws PublicApiException
{
final String personId = account3.createUser().getId();
publicApiClient.setRequestContext(new RequestContext(account3.getId(), account3Admin, "admin"));
String updatedFirstName = "Updated firstName";
Map params = new HashMap<>();
params.put("fields", "id,firstName");
HttpResponse response = people.update("people", personId, null, null, "{\n" + " \"firstName\": \"" + updatedFirstName + "\"\n" + "}", params,
"Expected 200 response when updating " + personId, 200);
Person updatedPerson = Person.parsePerson((JSONObject) response.getJsonResponse().get("entry"));
assertNotNull(updatedPerson.getId());
assertEquals(updatedFirstName, updatedPerson.getFirstName());
assertNull(updatedPerson.getEmail());
}
@Test
public void testUpdatePersonUpdateAsAdmin() throws Exception
{
final String personId = account3.createUser().getId();
publicApiClient.setRequestContext(new RequestContext(account3.getId(), account3Admin, "admin"));
String firstName = "updatedFirstName";
String lastName = "updatedLastName";
String description = "updatedDescription";
String email = "updated@example.com";
String skypeId = "updated.skype.id";
String googleId = "googleId";
String instantMessageId = "updated.user@example.com";
String jobTitle = "updatedJobTitle";
String location = "updatedLocation";
Company company = new Company("updatedOrganization", "updatedAddress1", "updatedAddress2", "updatedAddress3", "updatedPostcode", "updatedTelephone", "updatedFax", "updatedEmail");
String mobile = "mobile";
String telephone = "telephone";
String userStatus = "userStatus";
Boolean enabled = true;
Boolean emailNotificationsEnabled = false;
Map params = new HashMap<>();
params.put("fields", "id,firstName,lastName,description,avatarId,email,skypeId,googleId,instantMessageId,jobTitle,location,mobile,telephone,userStatus,emailNotificationsEnabled,enabled,company");
HttpResponse response = people.update("people", personId, null, null,
"{\n"
+ " \"firstName\": \"" + firstName + "\",\n"
+ " \"lastName\": \"" + lastName + "\",\n"
+ " \"description\": \"" + description + "\",\n"
+ " \"email\": \"" + email + "\",\n"
+ " \"skypeId\": \"" + skypeId + "\",\n"
+ " \"googleId\": \"" + googleId + "\",\n"
+ " \"instantMessageId\": \"" + instantMessageId + "\",\n"
+ " \"jobTitle\": \"" + jobTitle + "\",\n"
+ " \"location\": \"" + location + "\",\n"
+ " \"company\": {\n"
+ " \"organization\": \"" + company.getOrganization() + "\",\n"
+ " \"address1\": \"" + company.getAddress1() + "\",\n"
+ " \"address2\": \"" + company.getAddress2() + "\",\n"
+ " \"address3\": \"" + company.getAddress3() + "\",\n"
+ " \"postcode\": \"" + company.getPostcode() + "\",\n"
+ " \"telephone\": \"" + company.getTelephone() + "\",\n"
+ " \"fax\": \"" + company.getFax() + "\",\n"
+ " \"email\": \"" + company.getEmail() + "\"\n"
+ " },\n"
+ " \"mobile\": \"" + mobile + "\",\n"
+ " \"telephone\": \"" + telephone + "\",\n"
+ " \"userStatus\": \"" + userStatus + "\",\n"
+ " \"emailNotificationsEnabled\": \"" + emailNotificationsEnabled + "\",\n"
+ " \"enabled\": \"" + enabled + "\"\n"
+ "}", params,
"Expected 200 response when updating " + personId, 200);
Person updatedPerson = Person.parsePerson((JSONObject) response.getJsonResponse().get("entry"));
assertNotNull(updatedPerson.getId());
assertEquals(firstName, updatedPerson.getFirstName());
assertEquals(lastName, updatedPerson.getLastName());
assertEquals(description, updatedPerson.getDescription());
assertEquals(email, updatedPerson.getEmail());
assertEquals(skypeId, updatedPerson.getSkypeId());
assertEquals(googleId, updatedPerson.getGoogleId());
assertEquals(instantMessageId, updatedPerson.getInstantMessageId());
assertEquals(jobTitle, updatedPerson.getJobTitle());
assertEquals(location, updatedPerson.getLocation());
assertNotNull(updatedPerson.getCompany());
company.expected(updatedPerson.getCompany());
assertEquals(mobile, updatedPerson.getMobile());
assertEquals(telephone, updatedPerson.getTelephone());
assertEquals(userStatus, updatedPerson.getUserStatus());
assertEquals(emailNotificationsEnabled, updatedPerson.isEmailNotificationsEnabled());
assertEquals(enabled, updatedPerson.isEnabled());
// test ability to unset optional fields (could be one or more - here all) including individual company fields
response = people.update("people", personId, null, null,
"{\n"
+ " \"lastName\":null,\n"
+ " \"description\":null,\n"
+ " \"skypeId\":null,\n"
+ " \"googleId\":null,\n"
+ " \"instantMessageId\":null,\n"
+ " \"jobTitle\":null,\n"
+ " \"location\":null,\n"
+ " \"company\": {\n"
+ " \"address1\":null,\n"
+ " \"address2\":null,\n"
+ " \"address3\":null,\n"
+ " \"postcode\":null,\n"
+ " \"telephone\":null,\n"
+ " \"fax\":null,\n"
+ " \"email\":null\n"
+ " },\n"
+ " \"mobile\":null,\n"
+ " \"telephone\":null,\n"
+ " \"userStatus\":null\n"
+ "}", params,
"Expected 200 response when updating " + personId, 200);
updatedPerson = Person.parsePerson((JSONObject) response.getJsonResponse().get("entry"));
assertNotNull(updatedPerson.getId());
assertNull(updatedPerson.getLastName());
assertNull(updatedPerson.getDescription());
assertNull(updatedPerson.getSkypeId());
assertNull(updatedPerson.getGoogleId());
assertNull(updatedPerson.getInstantMessageId());
assertNull(updatedPerson.getJobTitle());
assertNull(updatedPerson.getLocation());
assertNotNull(updatedPerson.getCompany());
assertNotNull(updatedPerson.getCompany().getOrganization());
assertNull(updatedPerson.getCompany().getAddress1());
assertNull(updatedPerson.getCompany().getAddress2());
assertNull(updatedPerson.getCompany().getAddress3());
assertNull(updatedPerson.getCompany().getPostcode());
assertNull(updatedPerson.getCompany().getFax());
assertNull(updatedPerson.getCompany().getEmail());
assertNull(updatedPerson.getCompany().getTelephone());
assertNull(updatedPerson.getMobile());
assertNull(updatedPerson.getTelephone());
assertNull(updatedPerson.getUserStatus());
// test ability to unset company fields as a whole
response = people.update("people", personId, null, null,
"{\n"
+ " \"company\": {} \n"
+ "}", params,
"Expected 200 response when updating " + personId, 200);
updatedPerson = Person.parsePerson((JSONObject) response.getJsonResponse().get("entry"));
// note: empty company object is returned for backwards compatibility (with pre-existing getPerson API <= 5.1)
assertNotNull(updatedPerson.getCompany());
assertNull(updatedPerson.getCompany().getOrganization());
// set at least one company field
String updatedOrgName = "another org";
response = people.update("people", personId, null, null,
"{\n"
+ " \"company\": {\n"
+ " \"organization\":\""+updatedOrgName+"\"\n"
+ " }\n"
+ "}", params,
"Expected 200 response when updating " + personId, 200);
updatedPerson = Person.parsePerson((JSONObject) response.getJsonResponse().get("entry"));
assertNotNull(updatedPerson.getCompany());
assertEquals(updatedOrgName, updatedPerson.getCompany().getOrganization());
// test ability to unset company fields as a whole
response = people.update("people", personId, null, null,
"{\n"
+ " \"company\": null\n"
+ "}", params,
"Expected 200 response when updating " + personId, 200);
updatedPerson = Person.parsePerson((JSONObject) response.getJsonResponse().get("entry"));
// note: empty company object is returned for backwards compatibility (with pre-existing getPerson API <= 5.1)
assertNotNull(updatedPerson.getCompany());
assertNull(updatedPerson.getCompany().getOrganization());
}
@Test
public void testUpdatePersonEnabledNonAdminNotAllowed() throws PublicApiException
{
final String personId = account3.createUser().getId();
publicApiClient.setRequestContext(new RequestContext(account3.getId(), personId));
people.update("people", personId, null, null, "{\n" + " \"enabled\": \"false\"\n" + "}", null, "Expected 403 response when updating " + personId, 403);
}
@Test
public void testUpdatePersonEnabled() throws PublicApiException
{
// Non-admin user ID
final String personId = account3.createUser().getId();
// Use admin user credentials
publicApiClient.setRequestContext(new RequestContext(account3.getId(), account3Admin, "admin"));
// Admin can toggle enabled flag: false
{
Boolean enabled = false;
Map params = Collections.singletonMap("fields", "enabled");
Person updatedPerson = people.update(personId, qjson("{`enabled`:"+enabled+"}"), params, 200);
assertEquals(enabled, updatedPerson.isEnabled());
}
// Admin can toggle enabled flag: true
{
Boolean enabled = true;
Map params = Collections.singletonMap("fields", "enabled");
Person updatedPerson = people.update(personId, qjson("{`enabled`:"+enabled+"}"), params, 200);
assertEquals(enabled, updatedPerson.isEnabled());
}
// -ve test: enabled flag cannot be null/empty
people.update("people", personId, null, null, qjson("{ `enabled`: null }"), null, "Expected 400 response when updating " + personId, 400);
people.update("people", personId, null, null, qjson("{ `enabled`: `` }"), null, "Expected 400 response when updating " + personId, 400);
// Use non-admin user's own credentials
publicApiClient.setRequestContext(new RequestContext(account3.getId(), personId, "password"));
// Non-admin cannot set enabled flag
{
boolean origEnabled = people.getPerson(personId).isEnabled();
Boolean enabled = false;
// The test should change that we can't change this, otherwise it isn't effective
assertNotEquals(origEnabled, enabled);
Map params = Collections.singletonMap("fields", "enabled");
people.update(personId, qjson("{`enabled`:"+enabled+"}"), params, 403);
Person me = people.getPerson(personId);
assertEquals("Enabled state shouldn't have changed, but did", origEnabled, me.isEnabled());
}
}
@Test
public void testUpdatePersonAdminCannotBeDisabled() throws PublicApiException
{
publicApiClient.setRequestContext(new RequestContext(account3.getId(), account3Admin, "admin"));
Map params = new HashMap<>();
params.put("fields", "enabled");
people.update("people", account3Admin, null, null, "{\n" + " \"enabled\": \"" + false + "\"\n" + "}", params, "Expected 403 response when updating " + account3Admin, 403);
}
@Test
public void testUpdatePersonPasswordByThemself() throws PublicApiException
{
publicApiClient.setRequestContext(new RequestContext(account1.getId(), account1Admin, "admin"));
Person me = new Person();
me.setId(UUID.randomUUID().toString()+"@"+account1.getId());
me.setUserName(me.getId());
me.setFirstName("Jo");
me.setEmail(me.getId());
me.setEnabled(true);
me.setPassword("password123");
me = people.create(me);
publicApiClient.setRequestContext(new RequestContext(account1.getId(), me.getId(), "password123"));
// update with correct oldPassword
people.update(me.getId(), qjson("{ `oldPassword`:`password123`, `password`:`newpassword456` }"), 200);
// The old password should no longer work - therefore they are "unauthorized".
publicApiClient.setRequestContext(new RequestContext(account1.getId(), me.getId(), "password123"));
people.getPerson(me.getId(), 401);
// The new password should work.
publicApiClient.setRequestContext(new RequestContext(account1.getId(), me.getId(), "newpassword456"));
people.getPerson(me.getId());
// update with wrong oldPassword
people.update(me.getId(), qjson("{ `oldPassword`:`password123`, `password`:`newpassword456` }"), 403);
// update with no oldPassword
people.update(me.getId(), qjson("{ `password`:`newpassword456` }"), 400);
people.update(me.getId(), qjson("{ `oldPassword`:``, `password`:`newpassword456` }"), 400);
people.update(me.getId(), qjson("{ `oldPassword`:null, `password`:`newpassword456` }"), 400);
// update with no new password
people.update(me.getId(), qjson("{ `oldPassword`:`newpassword456` }"), 400);
people.update(me.getId(), qjson("{ `oldPassword`:`newpassword456`, `password`:`` }"), 400);
people.update(me.getId(), qjson("{ `oldPassword`:`newpassword456`, `password`:null }"), 400);
}
@Test
public void testUpdatePersonPasswordByAdmin() throws PublicApiException
{
final String personId = account3.createUser().getId();
final String networkId = account3.getId();
publicApiClient.setRequestContext(new RequestContext(networkId, account3Admin, "admin"));
String invalidPassword = "invalidPassword";
String updatedPassword = "newPassword";
people.update("people", personId, null, null, "{\n" + " \"password\": \"" + updatedPassword + "\"\n" + "}", null,
"Expected 200 response when updating " + personId, 200);
publicApiClient.setRequestContext(new RequestContext(networkId, personId, invalidPassword));
try
{
this.people.getPerson(personId);
fail("");
}
catch (PublicApiException e)
{
assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode());
}
publicApiClient.setRequestContext(new RequestContext(networkId, personId, updatedPassword));
this.people.getPerson(personId);
publicApiClient.setRequestContext(new RequestContext(networkId, account3Admin, "admin"));
// update with another new password but note that oldPassword is ignored (even if sent by admin)
String updatedPassword2 = "newPassword2";
people.update(personId, qjson("{ `password`:`" + updatedPassword2 + "`, `oldPassword`:`rubbish` }"), 200);
publicApiClient.setRequestContext(new RequestContext(networkId, personId, updatedPassword));
try
{
this.people.getPerson(personId);
fail("");
}
catch (PublicApiException e)
{
assertEquals(HttpStatus.SC_UNAUTHORIZED, e.getHttpResponse().getStatusCode());
}
publicApiClient.setRequestContext(new RequestContext(networkId, personId, updatedPassword2));
this.people.getPerson(personId);
// -ve: update with no new password
people.update(personId, qjson("{ `password`:`` }"), 400);
people.update(personId, qjson("{ `password`:null }"), 400);
}
@Test
public void testUpdatePersonWithNotUpdatableFields() throws PublicApiException
{
final String personId = account3.createUser().getId();
publicApiClient.setRequestContext(new RequestContext(account3.getId(), account3Admin, "admin"));
List> notUpdatableFields = new ArrayList<>();
notUpdatableFields.add(new Pair("userName", "userName"));
notUpdatableFields.add(new Pair("avatarId", "avatarId"));
notUpdatableFields.add(new Pair("statusUpdatedAt", "statusUpdatedAt"));
notUpdatableFields.add(new Pair("quota", "quota"));
notUpdatableFields.add(new Pair("quotaUsed", "quotaUsed"));
for (Pair notUpdatableField : notUpdatableFields)
{
people.update("people", personId, null, null, "{\n" + "\"" + notUpdatableField.getFirst() + "\": \"" + notUpdatableField.getSecond() + "\"\n" + "}", null,
"Expected 400 response when updating " + personId, 400);
}
}
private PublicApiClient.ListResponse listPeople(final PublicApiClient.Paging paging, String sortColumn, boolean asc, int statusCode) throws Exception
{
// sort params
final Map params = new HashMap<>();
if (sortColumn != null)
{
params.put("orderBy", sortColumn + " " + (asc ? "ASC" : "DESC"));
}
return listPeople(createParams(paging, params), statusCode);
}
private PublicApiClient.ListResponse listPeople(Map parameters, int expectedStatusCode) throws PublicApiException
{
HttpResponse response = people.getAll("people", null, null, null, parameters, "Failed to get people", expectedStatusCode);
JSONObject jsonList = (JSONObject) response.getJsonResponse().get("list");
if (jsonList == null)
{
return null;
}
return Person.parsePeople(response.getJsonResponse());
}
@Test
public void testListPeopleWithAspectNamesAndProperties() throws PublicApiException
{
publicApiClient.setRequestContext(new RequestContext(account3.getId(), account3Admin, "admin"));
personBob = new Person();
personBob.setId("bob@" + account3.getId());
personBob.setUserName(personBob.getId());
personBob.setFirstName("Bob");
personBob.setLastName("Cratchit");
personBob.setEmail("bob.cratchit@example.com");
personBob.setPassword("password");
personBob.setEnabled(true);
personBob.setProperties(Collections.singletonMap("papi:lunch", "Magical sandwich"));
people.create(personBob);
// Are aspectNames and properties left absent when not required?
{
PublicApiClient.ListResponse resp = listPeople(Collections.emptyMap(), 200);
assertNull(resp.getList().get(0).getAspectNames());
assertNull(resp.getList().get(0).getProperties());
}
// Are aspectNames and properties populated when requested?
{
Map parameters = Collections.singletonMap("include", "aspectNames,properties");
PublicApiClient.ListResponse resp = listPeople(parameters, 200);
Person bob = resp.getList().stream().
filter(p -> p.getUserName().equals(personBob.getId()))
.findFirst().get();
assertNotNull(bob.getAspectNames());
assertTrue(bob.getAspectNames().contains("papi:lunchable"));
assertNotNull(bob.getProperties());
assertEquals("Magical sandwich", bob.getProperties().get("papi:lunch"));
}
}
/**
* Tests the capability to sort and paginate the list of people orderBy =
* firstName ASC skip = 1, count = 3
*
* @throws Exception
*/
@Test
public void testPagingAndSortingByFirstNameAsc() throws Exception
{
publicApiClient.setRequestContext(new RequestContext(account4.getId(), account4Admin, "admin"));
// paging
int skipCount = 1;
int maxItems = 3;
int totalResults = 5;
PublicApiClient.Paging paging = getPaging(skipCount, maxItems, totalResults, totalResults);
// orderBy=firstName ASC
PublicApiClient.ListResponse resp = listPeople(paging, "firstName", true, 200);
List expectedList = new LinkedList<>();
expectedList.add(personAlice);
expectedList.add(personAliceD);
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 = 3
*
* @throws Exception
*/
@Test
public void testPagingAndSortingByFirstNameDesc() throws Exception
{
publicApiClient.setRequestContext(new RequestContext(account4.getId(), account4Admin, "admin"));
// paging
int skipCount = 1;
int maxItems = 3;
int totalResults = 5;
PublicApiClient.Paging paging = getPaging(skipCount, maxItems, totalResults, totalResults);
// orderBy=firstName DESC
PublicApiClient.ListResponse resp = listPeople(paging, "firstName", false, 200);
List expectedList = new LinkedList<>();
expectedList.add((Person) personBen);
expectedList.add((Person) personAlice);
expectedList.add((Person) personAliceD);
checkList(expectedList, paging.getExpectedPaging(), resp);
}
/**
* Tests the capability paginate the list of people verifies default
* sorting, skip = 1, count = 3
*
* @throws Exception
*/
@Test
public void testPagingAndDefaultSorting() throws Exception
{
publicApiClient.setRequestContext(new RequestContext(account4.getId(), account4Admin, "admin"));
// paging
int skipCount = 1;
int maxItems = 3;
int totalResults = 5;
PublicApiClient.Paging paging = getPaging(skipCount, maxItems, totalResults, totalResults);
PublicApiClient.ListResponse resp = listPeople(paging, null, false, 200);
List expectedList = new LinkedList<>();
expectedList.add((Person) personAlice);
expectedList.add((Person) personAliceD);
expectedList.add((Person) personBen);
checkList(expectedList, paging.getExpectedPaging(), resp);
}
/**
* Tests the capability to sort and paginate the list of people orderBy =
* username DESC skip = 1, count = 3
*
* @throws Exception
*/
@Test
public void testPagingAndSortingByIdDesc() throws Exception
{
publicApiClient.setRequestContext(new RequestContext(account4.getId(), account4Admin, "admin"));
// paging
int skipCount = 1;
int maxItems = 3;
int totalResults = 5;
PublicApiClient.Paging paging = getPaging(skipCount, maxItems, totalResults, totalResults);
// orderBy=userName DESC
PublicApiClient.ListResponse resp = listPeople(paging, "id", false, 200);
List expectedList = new LinkedList<>();
expectedList.add((Person) personBen);
expectedList.add((Person) personAliceD);
expectedList.add((Person) personAlice);
checkList(expectedList, paging.getExpectedPaging(), resp);
}
/**
* Tests the capability to sort and paginate the list of people orderBy =
* invalid sort key ASC skip = 1, count = 3
*
* @throws Exception
*/
@Test
public void testPagingAndSortingByInvalidSortKey() throws Exception
{
publicApiClient.setRequestContext(new RequestContext(account4.getId(), account4Admin, "admin"));
// paging
int skipCount = 1;
int maxItems = 3;
int totalResults = 5;
PublicApiClient.Paging paging = getPaging(skipCount, maxItems, totalResults, totalResults);
// orderBy=invalidSortKey ASC
listPeople(paging, "invalidSortKey", true, 400);
}
/**
* Tests the capability to sort and paginate the list of people orderBy =
* lastName ASC skip = 2, count = 3
*
* @throws Exception
*/
@Test
public void testPagingAndSortingByLastName() throws Exception
{
publicApiClient.setRequestContext(new RequestContext(account4.getId(), account4Admin, "admin"));
// paging
int skipCount = 2;
int maxItems = 3;
int totalResults = 5;
PublicApiClient.Paging paging = getPaging(skipCount, maxItems, totalResults, totalResults);
// orderBy=lastName ASC
PublicApiClient.ListResponse resp = listPeople(paging, "lastName", true, 200);
List expectedList = new LinkedList<>();
expectedList.add((Person) personBen);
expectedList.add((Person) personAliceD);
expectedList.add((Person) personAlice);
checkList(expectedList, paging.getExpectedPaging(), resp);
}
/**
* Tests the capability to sort and paginate the list of people orderBy =
* both firstName and lastName ASC skip = 1, count = 3
*
* @throws Exception
*/
@Test
public void testPagingAndSortingByFirstNameAndLastName() throws Exception
{
publicApiClient.setRequestContext(new RequestContext(account4.getId(), account4Admin, "admin"));
// paging
int skipCount = 1;
int maxItems = 3;
int totalResults = 5;
PublicApiClient.Paging paging = getPaging(skipCount, maxItems, totalResults, totalResults);
// orderBy=firstName,lastName ASC
PublicApiClient.ListResponse resp = listPeople(paging, "firstName,lastName", true, 200);
List expectedList = new LinkedList<>();
expectedList.add((Person) personAliceD);
expectedList.add((Person) personAlice);
expectedList.add((Person) personBen);
checkList(expectedList, paging.getExpectedPaging(), resp);
}
/**
* Tests reset password.
* POST:
*
* - {@literal :/alfresco/api//public/alfresco/versions/1/people//request-password-reset}
* - {@literal :/alfresco/api//public/alfresco/versions/1/people//reset-password}
*
*/
@Test
public void testResetPassword() throws Exception
{
// As Admin, create a user
setRequestContext(account1.getId(), account1Admin, "admin");
Person person = new Person();
person.setUserName("john.doe@" + account1.getId());
person.setFirstName("John");
person.setLastName("Doe");
person.setEmail("john.doe@alfresco.com");
person.setEnabled(true);
person.setEmailNotificationsEnabled(true);
person.setPassword("password");
people.create(person);
// un-authenticated API
setRequestContext(account1.getId(), null, null);
// Just try to login, to test the new created user credential
LoginTicket loginRequest = new LoginTicket();
loginRequest.setUserId(person.getUserName());
loginRequest.setPassword(person.getPassword());
// Authenticate and create a ticket
HttpResponse response = post("tickets", RestApiUtil.toJsonAsString(loginRequest), null, null, "authentication", 201);
LoginTicketResponse loginResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), LoginTicketResponse.class);
assertNotNull(loginResponse.getId());
assertNotNull(loginResponse.getUserId());
/**
* Reset Password
*/
// First make the service to send a synchronous email
ResetPasswordServiceImpl passwordService = applicationContext.getBean("resetPasswordService", ResetPasswordServiceImpl.class);
passwordService.setSendEmailAsynchronously(false);
// Get the 'mail' bean in a test mode.
EmailUtil emailUtil = new EmailUtil(applicationContext);
try
{
// Un-authenticated API
setRequestContext(account1.getId(), null, null);
// Reset email (just in case other tests didn't clean up...)
emailUtil.reset();
// Request reset password
Client client = new Client().setClient("share");
post(getRequestResetPasswordUrl(person.getUserName()), RestApiUtil.toJsonAsString(client), 202);
assertEquals("A reset password email should have been sent.", 1, emailUtil.getSentCount());
MimeMessage msg = emailUtil.getLastEmail();
assertNotNull("There should be an email.", msg);
assertEquals("Should've been only one email recipient.", 1, msg.getAllRecipients().length);
// Check the recipient is the person who requested the reset password
assertEquals(person.getEmail(), msg.getAllRecipients()[0].toString());
// There should be a subject
assertNotNull("There should be a subject.", msg.getSubject());
// Check the reset password url.
String resetPasswordUrl = (String) emailUtil.getLastEmailTemplateModelValue("reset_password_url");
assertNotNull("Wrong email is sent.", resetPasswordUrl);
// Get the workflow id and key
org.alfresco.util.Pair pair = getWorkflowIdAndKeyFromUrl(resetPasswordUrl);
assertNotNull("Workflow Id can't be null.", pair.getFirst());
assertNotNull("Workflow Key can't be null.", pair.getSecond());
// Reset the email helper, to get rid of the request reset password email
emailUtil.reset();
// Un-authenticated APIs as we are still using the 'setRequestContext(account1.getId(), null, null)' set above.
// Reset the password
PasswordReset passwordReset = new PasswordReset()
.setPassword("changed")
.setId(pair.getFirst())
.setKey(pair.getSecond());
post(getResetPasswordUrl(person.getUserName()), RestApiUtil.toJsonAsString(passwordReset), 202);
assertEquals("A reset password confirmation email should have been sent.", 1, emailUtil.getSentCount());
msg = emailUtil.getLastEmail();
assertNotNull("There should be an email.", msg);
assertEquals("Should've been only one email recipient.", 1, msg.getAllRecipients().length);
assertEquals(person.getEmail(), msg.getAllRecipients()[0].toString());
// There should be a subject
assertNotNull("There should be a subject.", msg.getSubject());
// Try to login with old credential
post("tickets", RestApiUtil.toJsonAsString(loginRequest), null, null, "authentication", 403);
// Set the new password
loginRequest.setPassword(passwordReset.getPassword());
response = post("tickets", RestApiUtil.toJsonAsString(loginRequest), null, null, "authentication", 201);
loginResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), LoginTicketResponse.class);
assertNotNull(loginResponse.getId());
assertNotNull(loginResponse.getUserId());
/*
* Negative tests
*/
// First, reset the email helper
emailUtil.reset();
// Try reset with the used workflow
// Note: we still return 202 response for security reasons
passwordReset.setPassword("changedAgain");
post(getResetPasswordUrl(person.getUserName()), RestApiUtil.toJsonAsString(passwordReset), 202);
assertEquals("No email should have been sent.", 0, emailUtil.getSentCount());
// Request reset password - Invalid user (user does not exist)
post(getRequestResetPasswordUrl(System.currentTimeMillis() + "noUser"), RestApiUtil.toJsonAsString(client), 202);
assertEquals("No email should have been sent.", 0, emailUtil.getSentCount());
// As Admin disable the user
setRequestContext(account1.getId(), account1Admin, "admin");
Map params = Collections.singletonMap("fields", "enabled");
Person updatedPerson = people.update(person.getUserName(), qjson("{`enabled`:" + false + "}"), params, 200);
assertFalse(updatedPerson.isEnabled());
// Un-authenticated API
setRequestContext(account1.getId(), null, null);
// Request reset password - Invalid user (user is disabled)
post(getRequestResetPasswordUrl(person.getUserName()), RestApiUtil.toJsonAsString(client), 202);
assertEquals("No email should have been sent.", 0, emailUtil.getSentCount());
// Client is not specified
client = new Client();
post(getRequestResetPasswordUrl(person.getUserName()), RestApiUtil.toJsonAsString(client), 400);
// Reset password
// First, reset the email helper and enable the user
emailUtil.reset();
// As Admin enable the user
setRequestContext(account1.getId(), account1Admin, "admin");
params = Collections.singletonMap("fields", "enabled");
updatedPerson = people.update(person.getUserName(), qjson("{`enabled`:" + true + "}"), params, 200);
assertTrue(updatedPerson.isEnabled());
// Un-authenticated API
setRequestContext(account1.getId(), null, null);
client = new Client().setClient("share");
post(getRequestResetPasswordUrl(person.getUserName()), RestApiUtil.toJsonAsString(client), 202);
assertEquals("A reset password email should have been sent.", 1, emailUtil.getSentCount());
resetPasswordUrl = (String) emailUtil.getLastEmailTemplateModelValue("reset_password_url");
// Check the reset password url.
assertNotNull("Wrong email is sent.", resetPasswordUrl);
// Get the workflow id and key
pair = getWorkflowIdAndKeyFromUrl(resetPasswordUrl);
assertNotNull("Workflow Id can't be null.", pair.getFirst());
assertNotNull("Workflow Key can't be null.", pair.getSecond());
// Reset the email helper, to get rid of the request reset password email
emailUtil.reset();
// Invalid request - password is not provided
PasswordReset passwordResetInvalid = new PasswordReset()
.setId(pair.getFirst())
.setKey(pair.getSecond());
post(getResetPasswordUrl(person.getUserName()), RestApiUtil.toJsonAsString(passwordResetInvalid), 400);
// Invalid request - workflow id is not provided
passwordResetInvalid.setPassword("changedAgain")
.setId(null);
post(getResetPasswordUrl(person.getUserName()), RestApiUtil.toJsonAsString(passwordResetInvalid), 400);
// Invalid request - workflow key is not provided
passwordResetInvalid.setId(pair.getFirst())
.setKey(null);
post(getResetPasswordUrl(person.getUserName()), RestApiUtil.toJsonAsString(passwordResetInvalid), 400);
// Invalid request - Invalid workflow id
// Note: we still return 202 response for security reasons
passwordResetInvalid = new PasswordReset()
.setPassword("changedAgain")
.setId("activiti$" + System.currentTimeMillis()) // Invalid Id
.setKey(pair.getSecond());
post(getResetPasswordUrl(person.getUserName()), RestApiUtil.toJsonAsString(passwordResetInvalid), 202);
assertEquals("No email should have been sent.", 0, emailUtil.getSentCount());
// Invalid request - Invalid workflow key
// Note: we still return 202 response for security reasons
passwordResetInvalid = new PasswordReset()
.setPassword("changedAgain")
.setId(pair.getFirst())
.setKey(GUID.generate()); // Invalid Key
post(getResetPasswordUrl(person.getUserName()), RestApiUtil.toJsonAsString(passwordResetInvalid), 202);
assertEquals("No email should have been sent.", 0, emailUtil.getSentCount());
// Invalid request (not the same user) - The given user id 'user1' does not match the person's user id who requested the password reset.
// Note: we still return 202 response for security reasons
passwordResetInvalid = new PasswordReset()
.setPassword("changedAgain")
.setId(pair.getFirst())
.setKey(pair.getSecond());
post(getResetPasswordUrl(user1), RestApiUtil.toJsonAsString(passwordResetInvalid), 202);
assertEquals("No email should have been sent.", 0, emailUtil.getSentCount());
}
finally
{
passwordService.setSendEmailAsynchronously(true);
emailUtil.reset();
}
}
private String getRequestResetPasswordUrl(String userId)
{
return URL_PEOPLE + '/' + userId + "/request-password-reset";
}
private String getResetPasswordUrl(String userId)
{
return URL_PEOPLE + '/' + userId + "/reset-password";
}
@Override
public String getScope()
{
return "public";
}
}