tidy up users resource supporting better updates. useraccounts resources has been removed along with change password template convenience api.

This commit is contained in:
Keith Woodlock
2012-05-25 12:23:59 +01:00
parent 898632790b
commit 6c71d027ce
22 changed files with 195 additions and 323 deletions
@@ -17,7 +17,7 @@ public class AppUserData {
private String lastname; private String lastname;
private String email; private String email;
private List<OfficeData> allowedOffices = new ArrayList<OfficeData>(); private List<OfficeLookup> allowedOffices = new ArrayList<OfficeLookup>();
private List<RoleData> availableRoles = new ArrayList<RoleData>(); private List<RoleData> availableRoles = new ArrayList<RoleData>();
private List<RoleData> selectedRoles = new ArrayList<RoleData>(); private List<RoleData> selectedRoles = new ArrayList<RoleData>();
@@ -85,11 +85,11 @@ public class AppUserData {
this.officeName = officeName; this.officeName = officeName;
} }
public List<OfficeData> getAllowedOffices() { public List<OfficeLookup> getAllowedOffices() {
return allowedOffices; return allowedOffices;
} }
public void setAllowedOffices(List<OfficeData> allowedOffices) { public void setAllowedOffices(List<OfficeLookup> allowedOffices) {
this.allowedOffices = allowedOffices; this.allowedOffices = allowedOffices;
} }
@@ -9,6 +9,7 @@ import javax.xml.bind.annotation.XmlRootElement;
public class AuthenticatedUserData { public class AuthenticatedUserData {
private String username; private String username;
private Long userId;
private String base64EncodedAuthenticationKey; private String base64EncodedAuthenticationKey;
private boolean authenticated = false; private boolean authenticated = false;
private Collection<String> permissions = new ArrayList<String>(); private Collection<String> permissions = new ArrayList<String>();
@@ -53,4 +54,12 @@ public class AuthenticatedUserData {
String base64EncodedAuthenticationKey) { String base64EncodedAuthenticationKey) {
this.base64EncodedAuthenticationKey = base64EncodedAuthenticationKey; this.base64EncodedAuthenticationKey = base64EncodedAuthenticationKey;
} }
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
} }
@@ -4,7 +4,7 @@ import java.io.Serializable;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "office lookup") @XmlRootElement(name = "officeLookup")
public class OfficeLookup implements Serializable { public class OfficeLookup implements Serializable {
private Long id; private Long id;
@@ -1,30 +0,0 @@
package org.mifosng.data.command;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class ChangePasswordCommand {
private String password;
private String passwordrepeat;
public ChangePasswordCommand() {
//
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPasswordrepeat() {
return passwordrepeat;
}
public void setPasswordrepeat(String passwordrepeat) {
this.passwordrepeat = passwordrepeat;
}
}
@@ -15,6 +15,7 @@ public class UserCommand implements Serializable {
private String firstname; private String firstname;
private String lastname; private String lastname;
private String password; private String password;
private String repeatPassword;
private String email; private String email;
private Long officeId; private Long officeId;
@@ -100,4 +101,12 @@ public class UserCommand implements Serializable {
public void setRoles(String... roles) { public void setRoles(String... roles) {
this.roles = roles; this.roles = roles;
} }
public String getRepeatPassword() {
return repeatPassword;
}
public void setRepeatPassword(String repeatPassword) {
this.repeatPassword = repeatPassword;
}
} }
@@ -79,6 +79,7 @@ public class ApplicationPagesRoutesController {
BasicAuthUserDetails userDetails = (BasicAuthUserDetails) authentication.getPrincipal(); BasicAuthUserDetails userDetails = (BasicAuthUserDetails) authentication.getPrincipal();
model.addAttribute("basicAuthKey", userDetails.getBasicAuthenticationKey()); model.addAttribute("basicAuthKey", userDetails.getBasicAuthenticationKey());
model.addAttribute("baseApiUrl", userDetails.getFullApiUrl()); model.addAttribute("baseApiUrl", userDetails.getFullApiUrl());
model.addAttribute("userId", userDetails.getUserId());
return "admin/accountsettings"; return "admin/accountsettings";
} }
@@ -65,7 +65,7 @@ public class ApiDelegatingAuthenticationProvider extends AbstractUserDetailsAuth
authorities.add(new SimpleGrantedAuthority(permission)); authorities.add(new SimpleGrantedAuthority(permission));
} }
User user = new User(authenticatedUserData.getUsername(), "[not needed]", authorities); User user = new User(authenticatedUserData.getUsername(), "[not needed]", authorities);
userDetails = new BasicAuthUserDetails(user, authenticatedUserData.getBase64EncodedAuthenticationKey(), platformApiUrl); userDetails = new BasicAuthUserDetails(user, authenticatedUserData.getBase64EncodedAuthenticationKey(), platformApiUrl, authenticatedUserData.getUserId());
} }
return userDetails; return userDetails;
@@ -80,8 +80,8 @@ public class ApiDelegatingAuthenticationProvider extends AbstractUserDetailsAuth
private HttpEntity<Object> authRequest() { private HttpEntity<Object> authRequest() {
HttpHeaders requestHeaders = new HttpHeaders(); HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Accept", "application/xml"); requestHeaders.set("Accept", "application/json");
requestHeaders.set("Content-Type", "application/xml"); requestHeaders.set("Content-Type", "application/json");
HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestHeaders); HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestHeaders);
return requestEntity; return requestEntity;
@@ -11,11 +11,13 @@ public class BasicAuthUserDetails implements UserDetails {
private final User user; private final User user;
private final String basicAuthenticationKey; private final String basicAuthenticationKey;
private final String fullApiUrl; private final String fullApiUrl;
private final Long userId;
public BasicAuthUserDetails(User user, String basicAuthenticationKey, String fullApiUrl) { public BasicAuthUserDetails(User user, String basicAuthenticationKey, String fullApiUrl, Long userId) {
this.user = user; this.user = user;
this.basicAuthenticationKey = basicAuthenticationKey; this.basicAuthenticationKey = basicAuthenticationKey;
this.fullApiUrl = fullApiUrl; this.fullApiUrl = fullApiUrl;
this.userId = userId;
} }
@Override @Override
@@ -60,4 +62,8 @@ public class BasicAuthUserDetails implements UserDetails {
public String getFullApiUrl() { public String getFullApiUrl() {
return this.fullApiUrl; return this.fullApiUrl;
} }
public Long getUserId() {
return userId;
}
} }
@@ -23,6 +23,7 @@ $(document).ready(function() {
// basic auth details // basic auth details
var base64 = "${basicAuthKey}"; var base64 = "${basicAuthKey}";
var baseApiUrl = "${baseApiUrl}"; var baseApiUrl = "${baseApiUrl}";
var userId = "${userId}";
// these helpers are registered for the jsViews and jsRender functionality to fix bug with display zero! // these helpers are registered for the jsViews and jsRender functionality to fix bug with display zero!
$.views.registerHelpers({ $.views.registerHelpers({
@@ -215,7 +216,6 @@ $(document).ready(function() {
dataType: 'json', dataType: 'json',
cache: false, cache: false,
beforeSend: function(xhr) { beforeSend: function(xhr) {
console.log("base64: " + base64);
xhr.setRequestHeader("Authorization", "Basic " + base64); xhr.setRequestHeader("Authorization", "Basic " + base64);
}, },
success: function(data, textStatus, jqXHR) { success: function(data, textStatus, jqXHR) {
@@ -249,7 +249,6 @@ $(document).ready(function() {
data: newFormData, data: newFormData,
cache: false, cache: false,
beforeSend: function(xhr) { beforeSend: function(xhr) {
console.log("base64: " + base64);
xhr.setRequestHeader("Authorization", "Basic " + base64); xhr.setRequestHeader("Authorization", "Basic " + base64);
}, },
success: saveSuccessFunction, success: saveSuccessFunction,
@@ -295,6 +294,78 @@ $(document).ready(function() {
}); });
} }
function popupDialogWithPostOnlyFormView(postOrPutUrl, submitType, titleCode, templateSelector, width, height, saveSuccessFunction) {
var dialogDiv = $("<div id='dialog-form'></div>");
var data = new Object();
var formHtml = $(templateSelector).render(data);
dialogDiv.append(formHtml);
var saveButton = jQuery.i18n.prop('dialog.button.save');
var cancelButton = jQuery.i18n.prop('dialog.button.cancel');
var buttonsOpts = {};
buttonsOpts[saveButton] = function() {
$('.multiSelectedItems option').each(function(i) {
$(this).attr("selected", "selected");
});
var newFormData = JSON.stringify($('#entityform').serializeObject());
console.log(newFormData);
var jqxhr = $.ajax({
url: postOrPutUrl,
type: submitType,
contentType: 'application/json',
dataType: 'json',
cache: false,
data: newFormData,
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Basic " + base64);
},
success: function(data, textStatus, jqXHR) {
dialogDiv.dialog("close");
$newtabs.tabs('load', tabIndex);
}
});
jqxhr.error(function(jqXHR, textStatus, errorThrown) {
handleXhrError(jqXHR, textStatus, errorThrown, "#formErrorsTemplate", "#formerrors");
});
};
buttonsOpts[cancelButton] = function() {$(this).dialog( "close" );};
dialogDiv.dialog({
title: jQuery.i18n.prop(titleCode),
width: width,
height: height,
modal: true,
buttons: buttonsOpts,
close: function() {
// if i dont do this, theres a problem with errors being appended to dialog view second time round
$(this).remove();
},
open: function (event, ui) {
$('.multiadd').click(function() {
return !$('.multiNotSelectedItems option:selected').remove().appendTo('#selectedItems');
});
$('.multiremove').click(function() {
return !$('.multiSelectedItems option:selected').remove().appendTo('#notSelectedItems');
});
$('.datepickerfield').datepicker({constrainInput: true, dateFormat: 'dd MM yy'});
$("#entityform textarea").first().focus();
$('#entityform input').first().focus();
}
}).dialog('open');
}
$("#tabs").tabs({ $("#tabs").tabs({
"ajaxOptions": { "ajaxOptions": {
type: 'GET', type: 'GET',
@@ -313,8 +384,7 @@ $(document).ready(function() {
$("#settings").html(tableHtml); $("#settings").html(tableHtml);
$('#changepassword').click(function(e) { $('#changepassword').click(function(e) {
var getUrl = baseApiUrl + 'useraccounts/current/password/template'; var putUrl = baseApiUrl + 'users/' + userId;
var putUrl = baseApiUrl + 'useraccounts/current/password';
var templateSelector = "#changePasswordFormTemplate"; var templateSelector = "#changePasswordFormTemplate";
var width = 600; var width = 600;
var height = 350; var height = 350;
@@ -324,13 +394,13 @@ $(document).ready(function() {
$("#tabs").tabs('load', 0); $("#tabs").tabs('load', 0);
} }
popupDialogWithFormView(getUrl, putUrl, 'PUT', 'dialog.title.update.password', templateSelector, width, height, saveSuccessFunction); popupDialogWithPostOnlyFormView(putUrl, 'PUT', 'dialog.title.update.password', templateSelector, width, height, saveSuccessFunction);
e.preventDefault(); e.preventDefault();
}); });
$('#changedetails').click(function(e) { $('#changedetails').click(function(e) {
var getAndPutUrl = baseApiUrl + 'useraccounts/current'; var getAndPutUrl = baseApiUrl + 'users/' + userId;
var templateSelector = "#userSettingsFormTemplate"; var templateSelector = "#userSettingsFormTemplate";
var width = 600; var width = 600;
var height = 350; var height = 350;
@@ -362,7 +432,7 @@ $(document).ready(function() {
<div id="content"> <div id="content">
<div id="tabs"> <div id="tabs">
<ul> <ul>
<li><a href="${baseApiUrl}useraccounts/current" title="settings"><spring:message code="tab.settings"/></a></li> <li><a href="${baseApiUrl}users/${userId}" title="settings"><spring:message code="tab.settings"/></a></li>
</ul> </ul>
<div id="settings"> <div id="settings">
</div> </div>
@@ -297,8 +297,8 @@
<label for="password"><spring:message code="form.label.new.password"/></label> <label for="password"><spring:message code="form.label.new.password"/></label>
<input id="password" name="password" title="" type="password" value="{{=password}}" size="75"/> <input id="password" name="password" title="" type="password" value="{{=password}}" size="75"/>
<label for="passwordrepeat"><spring:message code="form.label.repeat.new.password"/></label> <label for="repeatPassword"><spring:message code="form.label.repeat.new.password"/></label>
<input id="passwordrepeat" name="passwordrepeat" title="" type="password" value="{{=passwordrepeat}}" size="75"/> <input id="repeatPassword" name="repeatPassword" title="" type="password" value="{{=passwordrepeat}}" size="75"/>
</form> </form>
</script> </script>
@@ -41,6 +41,20 @@ public class DataValidatorBuilder {
this.ignoreNullValue = true; this.ignoreNullValue = true;
return this; return this;
} }
public DataValidatorBuilder equalToParameter(String linkedParameterName, Object linkedValue) {
if (value == null && linkedValue == null && ignoreNullValue) {
return this;
}
if (value != null && !value.equals(linkedValue)) {
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(linkedParameterName).append(".not.equal.to").append(parameter);
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(linkedParameterName).append(" is not equal to ").append(parameter).append(".");
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(), linkedParameterName, linkedValue, value);
dataValidationErrors.add(error);
}
return this;
}
public DataValidatorBuilder notNull() { public DataValidatorBuilder notNull() {
if (value == null && !ignoreNullValue) { if (value == null && !ignoreNullValue) {
@@ -12,6 +12,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import org.mifosng.data.AuthenticatedUserData; import org.mifosng.data.AuthenticatedUserData;
import org.mifosng.platform.user.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
@@ -33,8 +34,8 @@ public class AuthenticationApiResource {
private DaoAuthenticationProvider customAuthenticationProvider; private DaoAuthenticationProvider customAuthenticationProvider;
@POST @POST
@Consumes({MediaType.APPLICATION_XML}) @Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML}) @Produces({MediaType.APPLICATION_JSON})
public Response authenticate(@QueryParam("username") final String username, @QueryParam("password") final String password) { public Response authenticate(@QueryParam("username") final String username, @QueryParam("password") final String password) {
Authentication authentication = new UsernamePasswordAuthenticationToken(username, password); Authentication authentication = new UsernamePasswordAuthenticationToken(username, password);
@@ -51,6 +52,8 @@ public class AuthenticationApiResource {
} }
authenticatedUserData.setPermissions(permissions); authenticatedUserData.setPermissions(permissions);
authenticatedUserData.setAuthenticated(true); authenticatedUserData.setAuthenticated(true);
AppUser principal = (AppUser) authenticationCheck.getPrincipal();
authenticatedUserData.setUserId(principal.getId());
byte[] base64EncodedAuthenticationKey = Base64.encode(username + ":" + password); byte[] base64EncodedAuthenticationKey = Base64.encode(username + ":" + password);
authenticatedUserData.setBase64EncodedAuthenticationKey(new String(base64EncodedAuthenticationKey)); authenticatedUserData.setBase64EncodedAuthenticationKey(new String(base64EncodedAuthenticationKey));
@@ -1,73 +0,0 @@
package org.mifosng.platform.api;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.mifosng.data.AppUserData;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.command.ChangePasswordCommand;
import org.mifosng.data.command.UserCommand;
import org.mifosng.platform.user.service.AppUserReadPlatformService;
import org.mifosng.platform.user.service.AppUserWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/v1/useraccounts")
@Component
@Scope("singleton")
public class UserAccountApiResource {
@Autowired
private AppUserReadPlatformService appUserReadPlatformService;
@Autowired
private AppUserWritePlatformService appUserWritePlatformService;
@GET
@Path("current")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON})
public Response retrieveCurrentUser() {
AppUserData user = this.appUserReadPlatformService.retrieveCurrentUser();
return Response.ok().entity(user).build();
}
@PUT
@Path("current")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON})
public Response updateCurrentUser(UserCommand command) {
Long userId = this.appUserWritePlatformService.updateCurrentUser(command);
return Response.ok().entity(new EntityIdentifier(userId)).build();
}
@GET
@Path("current/password/template")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON})
public Response retrieveCurrentPasswordTemplate() {
return Response.ok().entity(new ChangePasswordCommand()).build();
}
@PUT
@Path("current/password")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON})
public Response updateCurrentUserPassword(ChangePasswordCommand command) {
Long userId = this.appUserWritePlatformService.updateCurrentUserPassword(command);
return Response.ok().entity(new EntityIdentifier(userId)).build();
}
}
@@ -270,22 +270,29 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
return lastname; return lastname;
} }
public void update(Set<Role> allRoles, Office office, String username, /**
String firstname, String lastname, String email) { * When updating details, any parameters with null values are ignored.
this.roles.clear(); */
this.roles = allRoles; public void update(Set<Role> allRoles, Office office, String username, String firstname, String lastname, String email) {
this.office = office; if (!allRoles.isEmpty()) {
this.username = username; this.roles.clear();
this.firstname = firstname; this.roles = allRoles;
this.lastname = lastname; }
this.email = email; if (office != null) {
} this.office = office;
}
public void update(String username, String firstname, String lastname, String email) { if (username != null) {
this.username = username; this.username = username;
this.firstname = firstname; }
this.lastname = lastname; if (firstname != null) {
this.email = email; this.firstname = firstname;
}
if (lastname != null) {
this.lastname = lastname;
}
if (email != null) {
this.email = email;
}
} }
public boolean canNotApproveLoanInPast() { public boolean canNotApproveLoanInPast() {
@@ -71,11 +71,10 @@ public class JpaUserDomainService implements UserDomainService {
generateKeyUsedForPasswordSalting(appUser); generateKeyUsedForPasswordSalting(appUser);
String unencodedPassword = appUser.getPassword(); String unencodedPassword = appUser.getPassword();
if (org.apache.commons.lang.StringUtils.isBlank(unencodedPassword)) { if (org.apache.commons.lang.StringUtils.isBlank(unencodedPassword) || "autogenerate".equalsIgnoreCase(unencodedPassword)) {
unencodedPassword = new RandomPasswordGenerator(13).generate(); unencodedPassword = new RandomPasswordGenerator(13).generate();
appUser.updatePassword(unencodedPassword);
} }
// update so encoding works.
appUser.updatePassword(unencodedPassword);
String encodePassword = this.applicationPasswordEncoder.encode(appUser); String encodePassword = this.applicationPasswordEncoder.encode(appUser);
appUser.updatePassword(encodePassword); appUser.updatePassword(encodePassword);
@@ -82,7 +82,7 @@ public class Role extends AbstractAuditableCustom<AppUser, Long> {
} }
/** /**
* When updating role details, any parameters with null values are ignored. * When updating details, any parameters with null values are ignored.
*/ */
public void update(String name, String description, List<Permission> selectedPermissions) { public void update(String name, String description, List<Permission> selectedPermissions) {
if (name != null) { if (name != null) {
@@ -11,6 +11,4 @@ public interface AppUserReadPlatformService {
AppUserData retrieveNewUserDetails(); AppUserData retrieveNewUserDetails();
AppUserData retrieveUser(Long userId); AppUserData retrieveUser(Long userId);
AppUserData retrieveCurrentUser();
} }
@@ -13,6 +13,7 @@ import javax.sql.DataSource;
import org.mifosng.data.AppUserData; import org.mifosng.data.AppUserData;
import org.mifosng.data.OfficeData; import org.mifosng.data.OfficeData;
import org.mifosng.data.OfficeLookup;
import org.mifosng.data.RoleData; import org.mifosng.data.RoleData;
import org.mifosng.platform.exceptions.PlatformResourceNotFoundException; import org.mifosng.platform.exceptions.PlatformResourceNotFoundException;
import org.mifosng.platform.organisation.service.OfficeReadPlatformService; import org.mifosng.platform.organisation.service.OfficeReadPlatformService;
@@ -78,7 +79,7 @@ public class AppUserReadPlatformServiceImpl implements AppUserReadPlatformServic
@Override @Override
public AppUserData retrieveNewUserDetails() { public AppUserData retrieveNewUserDetails() {
List<OfficeData> offices = new ArrayList<OfficeData>(officeReadPlatformService.retrieveAllOffices()); List<OfficeLookup> offices = new ArrayList<OfficeLookup>(officeReadPlatformService.retrieveAllOfficesForLookup());
List<RoleData> availableRoles = new ArrayList<RoleData>(this.roleReadPlatformService.retrieveAllRoles()); List<RoleData> availableRoles = new ArrayList<RoleData>(this.roleReadPlatformService.retrieveAllRoles());
@@ -94,7 +95,7 @@ public class AppUserReadPlatformServiceImpl implements AppUserReadPlatformServic
AppUser currentUser = context.authenticatedUser(); AppUser currentUser = context.authenticatedUser();
List<OfficeData> offices = new ArrayList<OfficeData>(officeReadPlatformService.retrieveAllOffices()); List<OfficeLookup> offices = new ArrayList<OfficeLookup>(officeReadPlatformService.retrieveAllOfficesForLookup());
List<RoleData> availableRoles = new ArrayList<RoleData>(this.roleReadPlatformService.retrieveAllRoles()); List<RoleData> availableRoles = new ArrayList<RoleData>(this.roleReadPlatformService.retrieveAllRoles());
@@ -125,38 +126,6 @@ public class AppUserReadPlatformServiceImpl implements AppUserReadPlatformServic
return userData; return userData;
} }
@Override
public AppUserData retrieveCurrentUser() {
AppUser currentUser = context.authenticatedUser();
List<OfficeData> offices = new ArrayList<OfficeData>(officeReadPlatformService.retrieveAllOffices());
List<RoleData> availableRoles = new ArrayList<RoleData>(this.roleReadPlatformService.retrieveAllRoles());
AppUser user = this.appUserRepository.findOne(usersThatMatch(currentUser.getOrganisation(), currentUser.getId()));
List<RoleData> userRoleData = new ArrayList<RoleData>();
Set<Role> userRoles = user.getRoles();
for (Role role : userRoles) {
userRoleData.add(role.toData());
}
AppUserData userData = new AppUserData(user.getId(),
user.getUsername(), user.getEmail(), user.getOrganisation()
.getId(), user.getOffice().getId(), user.getOffice()
.getName());
userData.setFirstname(user.getFirstname());
userData.setLastname(user.getLastname());
userData.setAllowedOffices(offices);
availableRoles.removeAll(userRoleData);
userData.setAvailableRoles(availableRoles);
userData.setSelectedRoles(userRoleData);
return userData;
}
private static final class AppUserMapper implements RowMapper<AppUserData> { private static final class AppUserMapper implements RowMapper<AppUserData> {
private final List<OfficeData> offices; private final List<OfficeData> offices;
@@ -1,6 +1,5 @@
package org.mifosng.platform.user.service; package org.mifosng.platform.user.service;
import org.mifosng.data.command.ChangePasswordCommand;
import org.mifosng.data.command.UserCommand; import org.mifosng.data.command.UserCommand;
public interface AppUserWritePlatformService { public interface AppUserWritePlatformService {
@@ -10,8 +9,4 @@ public interface AppUserWritePlatformService {
Long updateUser(final UserCommand command); Long updateUser(final UserCommand command);
void deleteUser(final Long userId); void deleteUser(final Long userId);
Long updateCurrentUser(UserCommand command);
Long updateCurrentUserPassword(ChangePasswordCommand command);
} }
@@ -9,7 +9,6 @@ import java.util.Set;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.mifosng.data.ApiParameterError; import org.mifosng.data.ApiParameterError;
import org.mifosng.data.command.ChangePasswordCommand;
import org.mifosng.data.command.UserCommand; import org.mifosng.data.command.UserCommand;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException; import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.mifosng.platform.exceptions.PlatformDataIntegrityException; import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
@@ -65,7 +64,7 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit
AppUser currentUser = context.authenticatedUser(); AppUser currentUser = context.authenticatedUser();
UserCommandValidator validator = new UserCommandValidator(command); UserCommandValidator validator = new UserCommandValidator(command);
validator.validate(); validator.validateForCreate();
Set<Role> allRoles = assembleSetOfRoles(command.getRoles()); Set<Role> allRoles = assembleSetOfRoles(command.getRoles());
@@ -104,21 +103,16 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit
AppUser currentUser = context.authenticatedUser(); AppUser currentUser = context.authenticatedUser();
UserCommandValidator validator = new UserCommandValidator(command); UserCommandValidator validator = new UserCommandValidator(command);
validator.validate(); validator.validateForUpdate();
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
if (command.getId() == null) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.user.id.cannot.be.blank", "The parameter id cannot be empty.", "id");
dataValidationErrors.add(error);
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
Set<Role> allRoles = assembleSetOfRoles(command.getRoles()); Set<Role> allRoles = assembleSetOfRoles(command.getRoles());
Office office = this.officeRepository.findOne(command.getOfficeId()); Office office = null;
if (office == null) { if (command.getOfficeId() != null) {
throw new PlatformResourceNotFoundException("error.msg.office.id.invalid", "Office with identifier {0} does not exist.", command.getOfficeId()); office = this.officeRepository.findOne(command.getOfficeId());
if (office == null) {
throw new PlatformResourceNotFoundException("error.msg.office.id.invalid", "Office with identifier {0} does not exist.", command.getOfficeId());
}
} }
AppUser userToUpdate = this.appUserRepository.findOne(usersThatMatch(currentUser.getOrganisation(), command.getId())); AppUser userToUpdate = this.appUserRepository.findOne(usersThatMatch(currentUser.getOrganisation(), command.getId()));
@@ -129,6 +123,17 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit
userToUpdate.update(allRoles, office, command.getUsername(), command.getFirstname(), command.getLastname(), command.getEmail()); userToUpdate.update(allRoles, office, command.getUsername(), command.getFirstname(), command.getLastname(), command.getEmail());
this.appUserRepository.saveAndFlush(userToUpdate); this.appUserRepository.saveAndFlush(userToUpdate);
if (command.getPassword() != null || command.getRepeatPassword() != null) {
PlatformUser dummyPlatformUser = new BasicPasswordEncodablePlatformUser(
userToUpdate.getId(),
userToUpdate.getUsername(), command.getPassword());
String newPasswordEncoded = this.platformPasswordEncoder.encode(dummyPlatformUser);
userToUpdate.updatePasswordOnFirstTimeLogin(newPasswordEncoded);
this.appUserRepository.saveAndFlush(userToUpdate);
}
return userToUpdate.getId(); return userToUpdate.getId();
} catch (DataIntegrityViolationException dve) { } catch (DataIntegrityViolationException dve) {
handleOfficeDataIntegrityIssues(command, dve); handleOfficeDataIntegrityIssues(command, dve);
@@ -153,44 +158,6 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit
this.appUserRepository.delete(userId); this.appUserRepository.delete(userId);
} }
@Transactional
@Override
public Long updateCurrentUser(UserCommand command) {
AppUser currentUser = context.authenticatedUser();
UserCommandValidator validator = new UserCommandValidator(command);
validator.validateAccountSettingDetails();
AppUser userToUpdate = this.appUserRepository.findOne(currentUser.getId());
userToUpdate.update(command.getUsername(), command.getFirstname(), command.getLastname(), command.getEmail());
this.appUserRepository.save(userToUpdate);
return userToUpdate.getId();
}
@Transactional
@Override
public Long updateCurrentUserPassword(ChangePasswordCommand command) {
AppUser currentUser = context.authenticatedUser();
ChangePasswordCommandValidator validator = new ChangePasswordCommandValidator(command);
validator.validate();
AppUser userToUpdate = this.appUserRepository.findOne(currentUser.getId());
PlatformUser dummyPlatformUser = new BasicPasswordEncodablePlatformUser(
userToUpdate.getId(),
userToUpdate.getUsername(), command.getPassword());
String newPasswordEncoded = this.platformPasswordEncoder.encode(dummyPlatformUser);
userToUpdate.updatePasswordOnFirstTimeLogin(newPasswordEncoded);
return userToUpdate.getId();
}
/* /*
* Guaranteed to throw an exception no matter what the data integrity issue is. * Guaranteed to throw an exception no matter what the data integrity issue is.
*/ */
@@ -1,41 +0,0 @@
package org.mifosng.platform.user.service;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.mifosng.data.ApiParameterError;
import org.mifosng.data.command.ChangePasswordCommand;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
public class ChangePasswordCommandValidator {
private final ChangePasswordCommand command;
public ChangePasswordCommandValidator(ChangePasswordCommand command) {
this.command = command;
}
public void validate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
if (StringUtils.isBlank(command.getPassword())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.changepassword.password.cannot.be.blank", "The parameter password cannot be blank.", "password");
dataValidationErrors.add(error);
}
if (StringUtils.isBlank(command.getPasswordrepeat())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.changepassword.passwordrepeat.cannot.be.blank", "The parameter passwordrepeat cannot be blank.", "passwordrepeat");
dataValidationErrors.add(error);
} else {
if (!command.getPasswordrepeat().equals(command.getPassword())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.changepassword.passwordrepeat.not.the.same", "The parameter passwordrepeat cannot be blank.", "passwordrepeat");
dataValidationErrors.add(error);
}
}
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
}
@@ -3,12 +3,10 @@ package org.mifosng.platform.user.service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.mifosng.data.ApiParameterError; import org.mifosng.data.ApiParameterError;
import org.mifosng.data.command.UserCommand; import org.mifosng.data.command.UserCommand;
import org.mifosng.platform.DataValidatorBuilder; import org.mifosng.platform.DataValidatorBuilder;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException; import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.springframework.util.ObjectUtils;
public class UserCommandValidator { public class UserCommandValidator {
@@ -21,72 +19,43 @@ public class UserCommandValidator {
public void validateForUpdate() { public void validateForUpdate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("role"); DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("user");
baseDataValidator.reset().parameter("id").value(command.getId()).notNull(); baseDataValidator.reset().parameter("id").value(command.getId()).notNull();
baseDataValidator.reset().parameter("username").value(command.getUsername()).ignoreIfNull().notBlank();
baseDataValidator.reset().parameter("firstname").value(command.getFirstname()).ignoreIfNull().notBlank(); baseDataValidator.reset().parameter("firstname").value(command.getFirstname()).ignoreIfNull().notBlank();
baseDataValidator.reset().parameter("lastname").value(command.getLastname()).ignoreIfNull().notBlank(); baseDataValidator.reset().parameter("lastname").value(command.getLastname()).ignoreIfNull().notBlank();
baseDataValidator.reset().parameter("email").value(command.getEmail()).ignoreIfNull().notBlank(); baseDataValidator.reset().parameter("email").value(command.getEmail()).ignoreIfNull().notBlank();
baseDataValidator.reset().parameter("officeId").value(command.getOfficeId()).ignoreIfNull().notNull();
baseDataValidator.reset().parameter("roles").value(command.getRoles()).ignoreIfNull().arrayNotEmpty(); baseDataValidator.reset().parameter("roles").value(command.getRoles()).ignoreIfNull().arrayNotEmpty();
baseDataValidator.reset().parameter("password").value(command.getPassword()).ignoreIfNull().notBlank(); baseDataValidator.reset().parameter("password").value(command.getPassword()).ignoreIfNull().notBlank();
baseDataValidator.reset().parameter("passwordRepeat").value(command.getPassword()).ignoreIfNull().notBlank(); baseDataValidator.reset().parameter("passwordRepeat").value(command.getPassword()).ignoreIfNull().notBlank();
baseDataValidator.reset().parameter("password").value(command.getPassword()).ignoreIfNull().equalToParameter("repeatPassword", command.getRepeatPassword());
baseDataValidator.reset().anyOfNotNull(command.getUsername(), command.getFirstname(), command.getLastname(), command.getEmail(), command.getOfficeId(),
command.getRoles(), command.getPassword(), command.getRepeatPassword());
if (!dataValidationErrors.isEmpty()) { if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
} }
} }
public void validate() { public void validateForCreate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
validateAccountSettings(dataValidationErrors); DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("user");
if (command.getOfficeId() == null || command.getOfficeId().equals(Long.valueOf(-1))) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.user.office.cannot.be.blank", "The parameter officeId cannot be blank.", "officeId");
dataValidationErrors.add(error);
}
if (ObjectUtils.isEmpty(command.getRoles())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.user.roles.cannot.be.blank", "The parameter selectedItems cannot be blank.", "selectedItems");
dataValidationErrors.add(error);
}
baseDataValidator.reset().parameter("username").value(command.getUsername()).notBlank();
baseDataValidator.reset().parameter("firstname").value(command.getFirstname()).notBlank();
baseDataValidator.reset().parameter("lastname").value(command.getLastname()).notBlank();
baseDataValidator.reset().parameter("email").value(command.getEmail()).notBlank();
baseDataValidator.reset().parameter("officeId").value(command.getOfficeId()).notNull();
baseDataValidator.reset().parameter("roles").value(command.getRoles()).arrayNotEmpty();
if (!dataValidationErrors.isEmpty()) { if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
} }
} }
public void validateAccountSettingDetails() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
validateAccountSettings(dataValidationErrors);
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
private void validateAccountSettings(List<ApiParameterError> dataValidationErrors) {
if (StringUtils.isBlank(command.getUsername())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.user.username.cannot.be.blank", "The parameter username cannot be blank.", "username");
dataValidationErrors.add(error);
}
if (StringUtils.isBlank(command.getFirstname())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.user.firstname.cannot.be.blank", "The parameter firstname cannot be blank.", "firstname");
dataValidationErrors.add(error);
}
if (StringUtils.isBlank(command.getLastname())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.user.lastname.cannot.be.blank", "The parameter lastname cannot be blank.", "lastname");
dataValidationErrors.add(error);
}
if (StringUtils.isBlank(command.getEmail())) {
ApiParameterError error = ApiParameterError.parameterError("validation.msg.user.email.cannot.be.blank", "The parameter email cannot be blank.", "email");
dataValidationErrors.add(error);
}
}
} }