Merged mward/5.2.n-repo1544-update-self (5.2.1) to 5.2.N (5.2.1)

132914 mward: REPO-1544: allow people to update their own password


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@132996 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Matt Ward
2016-11-22 10:26:06 +00:00
parent 396e471807
commit 3c8c8f03ac
5 changed files with 124 additions and 34 deletions

View File

@@ -626,6 +626,7 @@
<property name="siteService" ref="SiteService" /> <property name="siteService" ref="SiteService" />
<property name="nodeService" ref="NodeService" /> <property name="nodeService" ref="NodeService" />
<property name="personService" ref="PersonService" /> <property name="personService" ref="PersonService" />
<property name="unprotectedPersonService" ref="personService" />
<property name="authenticationService" ref="AuthenticationService" /> <property name="authenticationService" ref="AuthenticationService" />
<property name="authorityService" ref="AuthorityService" /> <property name="authorityService" ref="AuthorityService" />
<property name="contentUsageService" ref="contentUsageImpl" /> <property name="contentUsageService" ref="contentUsageImpl" />

View File

@@ -31,6 +31,7 @@ import java.util.*;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.query.PagingRequest; import org.alfresco.query.PagingRequest;
import org.alfresco.query.PagingResults; import org.alfresco.query.PagingResults;
import org.alfresco.repo.security.authentication.AuthenticationException;
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;
@@ -103,6 +104,7 @@ public class PeopleImpl implements People
protected SiteService siteService; protected SiteService siteService;
protected NodeService nodeService; protected NodeService nodeService;
protected PersonService personService; protected PersonService personService;
protected PersonService unprotectedPersonService;
protected AuthenticationService authenticationService; protected AuthenticationService authenticationService;
protected AuthorityService authorityService; protected AuthorityService authorityService;
protected ContentUsageService contentUsageService; protected ContentUsageService contentUsageService;
@@ -143,8 +145,13 @@ public class PeopleImpl implements People
{ {
this.personService = personService; this.personService = personService;
} }
public void setAuthenticationService(AuthenticationService authenticationService) public void setUnprotectedPersonService(PersonService unprotectedPersonService)
{
this.unprotectedPersonService = unprotectedPersonService;
}
public void setAuthenticationService(AuthenticationService authenticationService)
{ {
this.authenticationService = authenticationService; this.authenticationService = authenticationService;
} }
@@ -512,8 +519,10 @@ public class PeopleImpl implements People
{ {
MutableAuthenticationService mutableAuthenticationService = (MutableAuthenticationService) authenticationService; MutableAuthenticationService mutableAuthenticationService = (MutableAuthenticationService) authenticationService;
if (!isAdminAuthority()) String currentUserId = AuthenticationUtil.getFullyAuthenticatedUser();
if (!isAdminAuthority() && !currentUserId.equalsIgnoreCase(personId))
{ {
// The user is not an admin user and is not attempting to update *their own* details.
throw new PermissionDeniedException(); throw new PermissionDeniedException();
} }
@@ -522,9 +531,30 @@ public class PeopleImpl implements People
if (person.getPassword() != null && !person.getPassword().isEmpty()) if (person.getPassword() != null && !person.getPassword().isEmpty())
{ {
// an Admin user can update without knowing the original pass - but // An admin user can update without knowing the original pass - but must know their own!
// must know their own! char[] newPassword = person.getPassword().toCharArray();
mutableAuthenticationService.setAuthentication(personIdToUpdate, person.getPassword().toCharArray()); if (isAdminAuthority())
{
mutableAuthenticationService.setAuthentication(personIdToUpdate, newPassword);
}
else
{
// Non-admin users can update their own password, but must provide their current password.
if (person.getOldPassword() == null)
{
throw new PermissionDeniedException();
}
char[] oldPassword = person.getOldPassword().toCharArray();
try
{
mutableAuthenticationService.updateAuthentication(personIdToUpdate, oldPassword, newPassword);
}
catch (AuthenticationException e)
{
// TODO: add to exception mappings/handler
throw new PermissionDeniedException("Incorrect existing password.");
}
}
} }
if (person.isEnabled() != null) if (person.isEnabled() != null)
@@ -553,8 +583,16 @@ public class PeopleImpl implements People
Map<String, Object> customProps = person.getProperties(); Map<String, Object> customProps = person.getProperties();
properties.putAll(nodes.mapToNodeProperties(customProps)); properties.putAll(nodes.mapToNodeProperties(customProps));
} }
personService.setPersonProperties(personIdToUpdate, properties, false); // The person service only allows admin users to set the properties by default.
if (!isAdminAuthority())
{
unprotectedPersonService.setPersonProperties(personIdToUpdate, properties, false);
}
else
{
personService.setPersonProperties(personIdToUpdate, properties, false);
}
// Update custom aspects // Update custom aspects
nodes.updateCustomAspects(personNodeRef, person.getAspectNames(), EXCLUDED_ASPECTS); nodes.updateCustomAspects(personNodeRef, person.getAspectNames(), EXCLUDED_ASPECTS);

View File

@@ -67,6 +67,7 @@ public class Person
protected String description; protected String description;
protected Company company; protected Company company;
protected String password; protected String password;
protected String oldPassword;
protected Map<String, Object> properties; protected Map<String, Object> properties;
protected List<String> aspectNames; protected List<String> aspectNames;
@@ -241,6 +242,11 @@ public class Person
this.password = password; this.password = password;
} }
public void setOldPassword(String oldPassword)
{
this.oldPassword = oldPassword;
}
public NodeRef getAvatarId() public NodeRef getAvatarId()
{ {
return avatarId; return avatarId;
@@ -356,6 +362,11 @@ public class Person
return this.password; return this.password;
} }
public String getOldPassword()
{
return oldPassword;
}
public Map<String, Object> getProperties() public Map<String, Object> getProperties()
{ {
return properties; return properties;

View File

@@ -775,15 +775,15 @@ public class TestPeople extends EnterpriseTestApi
people.update("people", personId, null, null, "{\n" + " \"firstName\": \"Updated firstName\"\n" + "}", null, "Expected 401 response when updating " + personId, 401); people.update("people", personId, null, null, "{\n" + " \"firstName\": \"Updated firstName\"\n" + "}", null, "Expected 401 response when updating " + personId, 401);
} }
@Test // @Test
public void testUpdatePersonNonAdminNotAllowed() throws PublicApiException // public void testUpdatePersonNonSelfAndNonAdminDisallowed() throws PublicApiException
{ // {
final String personId = account3PersonIt.next(); // final String personId = account3PersonIt.next();
publicApiClient.setRequestContext(new RequestContext(account3.getId(), personId)); // publicApiClient.setRequestContext(new RequestContext(account3.getId(), personId));
//
people.update("people", personId, null, null, "{\n" + " \"firstName\": \"Updated firstName\"\n" + "}", null, "Expected 403 response when updating " + personId, 403); // people.update("people", personId, null, null, "{\n" + " \"firstName\": \"Updated firstName\"\n" + "}", null, "Expected 403 response when updating " + personId, 403);
} // }
@Test @Test
public void testUpdatePersonNonexistentPerson() throws PublicApiException public void testUpdatePersonNonexistentPerson() throws PublicApiException
@@ -955,17 +955,39 @@ public class TestPeople extends EnterpriseTestApi
people.update("people", account3Admin, null, null, "{\n" + " \"enabled\": \"" + false + "\"\n" + "}", params, "Expected 403 response when updating " + account3Admin, 403); people.update("people", account3Admin, null, null, "{\n" + " \"enabled\": \"" + false + "\"\n" + "}", params, "Expected 403 response when updating " + account3Admin, 403);
} }
@Test @Test
public void testUpdatePersonPasswordNonAdminNotAllowed() throws PublicApiException public void testUpdatePersonPasswordByThemself() throws PublicApiException
{ {
final String personId = account3PersonIt.next(); publicApiClient.setRequestContext(new RequestContext(account1.getId(), account1Admin, "admin"));
publicApiClient.setRequestContext(new RequestContext(account3.getId(), personId)); 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"));
people.update("people", personId, null, null, "{\n" + " \"password\": \"newPassword\"\n" + "}", null, "Expected 403 response when updating " + personId, 403); // 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` }"), 403);
}
@Test @Test
public void testUpdatePersonPassword() throws PublicApiException public void testUpdatePersonPasswordByAdmin() throws PublicApiException
{ {
final String personId = account3PersonIt.next(); final String personId = account3PersonIt.next();
final String networkId = account3.getId(); final String networkId = account3.getId();

View File

@@ -1067,16 +1067,28 @@ public class PublicApiClient
public Person getPerson(String personId) throws PublicApiException public Person getPerson(String personId) throws PublicApiException
{ {
HttpResponse response = getSingle("people", personId, null, null, "Failed to get person"); return getPerson(personId, 200);
}
public Person getPerson(String personId, int expectedStatus) throws PublicApiException
{
HttpResponse response = getSingle("people", personId, null, null, "Failed to get person", expectedStatus);
if(logger.isDebugEnabled()) if(logger.isDebugEnabled())
{ {
logger.debug(response); logger.debug(response);
} }
System.out.println(response); System.out.println(response);
Person site = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); if (response != null && response.getJsonResponse() != null)
return site; {
JSONObject entry = (JSONObject) response.getJsonResponse().get("entry");
if (entry != null)
{
return Person.parsePerson(entry);
}
}
return null;
} }
public Person update(String personId, Person person) throws PublicApiException public Person update(String personId, Person person) throws PublicApiException
@@ -1092,8 +1104,15 @@ public class PublicApiClient
public Person update(String personId, String json, int expectedStatus) throws PublicApiException public Person update(String personId, String json, int expectedStatus) throws PublicApiException
{ {
HttpResponse response = update("people", personId, null, null, json, null, "Failed to update person", expectedStatus); HttpResponse response = update("people", personId, null, null, json, null, "Failed to update person", expectedStatus);
Person retSite = Person.parsePerson((JSONObject)response.getJsonResponse().get("entry")); if (response != null && response.getJsonResponse() != null)
return retSite; {
JSONObject entry = (JSONObject) response.getJsonResponse().get("entry");
if (entry != null)
{
return Person.parsePerson(entry);
}
}
return null;
} }
public Person create(Person person) throws PublicApiException public Person create(Person person) throws PublicApiException
@@ -1107,11 +1126,10 @@ public class PublicApiClient
HttpResponse response = create("people", null, null, null, jsonizer.toJSON().toString(), "Failed to create person", expectedStatus); HttpResponse response = create("people", null, null, null, jsonizer.toJSON().toString(), "Failed to create person", expectedStatus);
if ((response != null) && (response.getJsonResponse() != null)) if ((response != null) && (response.getJsonResponse() != null))
{ {
Object entry = response.getJsonResponse().get("entry"); JSONObject entry = (JSONObject) response.getJsonResponse().get("entry");
// entry will be null if there is an "error" data structure returned instead.
if (entry != null) if (entry != null)
{ {
return Person.parsePerson((JSONObject) entry); return Person.parsePerson(entry);
} }
} }
return null; return null;