add useraccounts resource which is responsible for supporting capabilities that allow a user update their account details.

This commit is contained in:
Keith Woodlock
2012-05-14 17:00:40 +01:00
parent 5ccecb8bc4
commit 06ac2869b7
10 changed files with 207 additions and 263 deletions
@@ -2,7 +2,6 @@ package org.mifosng.ui;
import java.util.Collection; import java.util.Collection;
import org.mifosng.data.AppUserData;
import org.mifosng.data.ClientData; import org.mifosng.data.ClientData;
import org.mifosng.data.ClientDataWithAccountsData; import org.mifosng.data.ClientDataWithAccountsData;
import org.mifosng.data.EntityIdentifier; import org.mifosng.data.EntityIdentifier;
@@ -17,7 +16,6 @@ import org.mifosng.data.PermissionData;
import org.mifosng.data.RoleData; import org.mifosng.data.RoleData;
import org.mifosng.data.command.AdjustLoanTransactionCommand; import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.CalculateLoanScheduleCommand; import org.mifosng.data.command.CalculateLoanScheduleCommand;
import org.mifosng.data.command.ChangePasswordCommand;
import org.mifosng.data.command.EnrollClientCommand; import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.data.command.LoanStateTransitionCommand; import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand; import org.mifosng.data.command.LoanTransactionCommand;
@@ -35,10 +33,6 @@ public interface CommonRestOperations {
void updateProtectedResource(ProtectedResourceDetails loadProtectedResourceDetailsById); void updateProtectedResource(ProtectedResourceDetails loadProtectedResourceDetailsById);
AppUserData retrieveCurrentUser();
EntityIdentifier updateCurrentUserPassword(ChangePasswordCommand command);
Collection<RoleData> retrieveAllRoles(); Collection<RoleData> retrieveAllRoles();
RoleData retrieveRole(Long roleId); RoleData retrieveRole(Long roleId);
@@ -6,7 +6,6 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import org.mifosng.configuration.ApplicationConfigurationService; import org.mifosng.configuration.ApplicationConfigurationService;
import org.mifosng.data.AppUserData;
import org.mifosng.data.ClientData; import org.mifosng.data.ClientData;
import org.mifosng.data.ClientDataWithAccountsData; import org.mifosng.data.ClientDataWithAccountsData;
import org.mifosng.data.ClientList; import org.mifosng.data.ClientList;
@@ -29,7 +28,6 @@ import org.mifosng.data.RoleData;
import org.mifosng.data.RoleList; import org.mifosng.data.RoleList;
import org.mifosng.data.command.AdjustLoanTransactionCommand; import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.CalculateLoanScheduleCommand; import org.mifosng.data.command.CalculateLoanScheduleCommand;
import org.mifosng.data.command.ChangePasswordCommand;
import org.mifosng.data.command.EnrollClientCommand; import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.data.command.LoanStateTransitionCommand; import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand; import org.mifosng.data.command.LoanTransactionCommand;
@@ -547,25 +545,6 @@ public class CommonRestOperationsImpl implements CommonRestOperations {
} }
} }
@Override
public EntityIdentifier updateCurrentUserPassword(
ChangePasswordCommand command) {
try {
URI restUri = URI.create(getBaseServerUrl().concat(
"api/protected/admin/user/current/password"));
ResponseEntity<EntityIdentifier> s = this.oauthRestServiceTemplate
.postForEntity(restUri,
createUpdateCurrentUserPasswordRequest(command),
EntityIdentifier.class);
return s.getBody();
} catch (HttpStatusCodeException e) {
ErrorResponseList errorList = parseErrors(e);
throw new ClientValidationException(errorList.getErrors());
}
}
private HttpEntity<UserCommand> createUserRequest(final UserCommand command) { private HttpEntity<UserCommand> createUserRequest(final UserCommand command) {
HttpHeaders requestHeaders = new HttpHeaders(); HttpHeaders requestHeaders = new HttpHeaders();
@@ -577,18 +556,6 @@ public class CommonRestOperationsImpl implements CommonRestOperations {
return requestEntity; return requestEntity;
} }
private HttpEntity<ChangePasswordCommand> createUpdateCurrentUserPasswordRequest(
final ChangePasswordCommand command) {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Accept", "application/xml");
requestHeaders.set("Content-Type", "application/xml");
HttpEntity<ChangePasswordCommand> requestEntity = new HttpEntity<ChangePasswordCommand>(
command, requestHeaders);
return requestEntity;
}
private HttpEntity<RoleCommand> roleRequest(final RoleCommand command) { private HttpEntity<RoleCommand> roleRequest(final RoleCommand command) {
HttpHeaders requestHeaders = new HttpHeaders(); HttpHeaders requestHeaders = new HttpHeaders();
@@ -600,17 +567,6 @@ public class CommonRestOperationsImpl implements CommonRestOperations {
return requestEntity; return requestEntity;
} }
@Override
public AppUserData retrieveCurrentUser() {
URI restUri = URI.create(getBaseServerUrl().concat(
"api/protected/admin/user/current"));
ResponseEntity<AppUserData> s = this.oauthRestServiceTemplate.exchange(
restUri, HttpMethod.GET, emptyRequest(), AppUserData.class);
return s.getBody();
}
@Override @Override
public Collection<RoleData> retrieveAllRoles() { public Collection<RoleData> retrieveAllRoles() {
try { try {
@@ -4,23 +4,14 @@ import java.util.Collection;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.mifosng.data.AppUserData;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.ErrorResponse; import org.mifosng.data.ErrorResponse;
import org.mifosng.data.command.ChangePasswordCommand;
import org.mifosng.data.command.UserCommand;
import org.mifosng.ui.CommonRestOperations;
import org.mifosng.ui.loanproduct.ClientValidationException; import org.mifosng.ui.loanproduct.ClientValidationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
/** /**
* Controller for user and organisation administration functions. * Controller for user and organisation administration functions.
@@ -28,13 +19,6 @@ import org.springframework.web.bind.annotation.ResponseStatus;
@Controller @Controller
public class AdministrationController { public class AdministrationController {
private final CommonRestOperations commonRestOperations;
@Autowired
public AdministrationController(final CommonRestOperations commonRestOperations) {
this.commonRestOperations = commonRestOperations;
}
@ExceptionHandler(AccessDeniedException.class) @ExceptionHandler(AccessDeniedException.class)
public String accessDeniedException() { public String accessDeniedException() {
return "unAuthorizedAction"; return "unAuthorizedAction";
@@ -63,46 +47,4 @@ public class AdministrationController {
public String userSettingsScreen() { public String userSettingsScreen() {
return "admin/accountsettings"; return "admin/accountsettings";
} }
@RequestMapping(consumes="application/json", produces="application/json", value = "org/admin/settings/details", method = RequestMethod.GET)
public @ResponseBody AppUserData viewUserDetails() {
return this.commonRestOperations.retrieveCurrentUser();
}
@RequestMapping(consumes="application/x-www-form-urlencoded", produces="application/json", value = "org/admin/settings/details", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.OK)
public @ResponseBody EntityIdentifier updateUserDetails(
@RequestParam(value="username", required=false) String username,
@RequestParam(value="firstname", required=false) String firstname,
@RequestParam(value="lastname", required=false) String lastname,
@RequestParam(value="email", required=false) String email) {
UserCommand command = new UserCommand();
command.setUsername(username);
command.setFirstname(firstname);
command.setLastname(lastname);
command.setEmail(email);
return this.commonRestOperations.updateCurrentUserDetails(command);
}
@RequestMapping(consumes="application/json", produces="application/json", value = "org/admin/settings/password", method = RequestMethod.GET)
public @ResponseBody ChangePasswordCommand viewChangePasswordDetails() {
return new ChangePasswordCommand();
}
@RequestMapping(consumes="application/x-www-form-urlencoded", produces="application/json", value = "org/admin/settings/password", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.OK)
public @ResponseBody EntityIdentifier updateUserDetails(
@RequestParam(value="password", required=false) String password,
@RequestParam(value="passwordrepeat", required=false) String passwordrepeat) {
ChangePasswordCommand command = new ChangePasswordCommand();
command.setPassword(password);
command.setPasswordrepeat(passwordrepeat);
return this.commonRestOperations.updateCurrentUserPassword(command);
}
} }
@@ -59,9 +59,9 @@ $(document).ready(function() {
return false; return false;
} }
}, },
globalDate: function(dateParts) { globalDate: function(localDateAsISOString) {
try { try {
var dateParts = localDateAsISOString.split("-")
var year = dateParts[0]; var year = dateParts[0];
var month = parseInt(dateParts[1]) - 1; // month is zero indexed var month = parseInt(dateParts[1]) - 1; // month is zero indexed
var day = dateParts[2]; var day = dateParts[2];
@@ -74,9 +74,9 @@ $(document).ready(function() {
return "??"; return "??";
} }
}, },
globalDateTime: function(dateParts) { globalDateTime: function(dateInMillis) {
try { try {
var d = new Date(dateParts); var d = new Date(dateInMillis);
return Globalize.format(d,"F"); return Globalize.format(d,"F");
} catch(e) { } catch(e) {
@@ -118,17 +118,25 @@ $(document).ready(function() {
removeErrors(placeholderDiv); removeErrors(placeholderDiv);
var jsonErrors = JSON.parse(jqXHR.responseText); var jsonErrors = JSON.parse(jqXHR.responseText);
var valErrors = jsonErrors.errors;
var errorArray = new Array(); var errorArray = new Array();
var arrayIndex = 0; var arrayIndex = 0;
$.each(jsonErrors, function() { $.each(valErrors, function() {
var fieldId = '#' + this.field; var fieldId = '#' + this.parameterName;
$(fieldId).addClass("ui-state-error"); $(fieldId).addClass("ui-state-error");
var errorObj = new Object(); var errorObj = new Object();
errorObj.field = this.field; errorObj.field = this.parameterName;
errorObj.code = this.code; errorObj.code = this.userMessageGlobalisationCode;
errorObj.message = jQuery.i18n.prop(this.code, this.args);
var argArray = new Array();
var argArrayIndex = 0;
$.each(this.args, function() {
argArray[argArrayIndex] = this.value;
argArrayIndex++;
});
// hardcoded support for six arguments
errorObj.message = jQuery.i18n.prop(this.userMessageGlobalisationCode, argArray[0], argArray[1], argArray[2], argArray[3], argArray[4], argArray[5]);
errorObj.value = this.value; errorObj.value = this.value;
errorArray[arrayIndex] = errorObj; errorArray[arrayIndex] = errorObj;
@@ -148,6 +156,29 @@ $(document).ready(function() {
} }
} }
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
if (this.name === 'selectedItems' || this.name === 'notSelectedItems') {
o[this.name] = new Array();
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
}
});
return o;
};
function showNotAvailableDialog(titleCode) { function showNotAvailableDialog(titleCode) {
var dialogDiv = $("<div id='notavailable-dialog-form'></div>"); var dialogDiv = $("<div id='notavailable-dialog-form'></div>");
@@ -171,16 +202,16 @@ $(document).ready(function() {
}).dialog('open'); }).dialog('open');
} }
function popupDialogWithFormView(url, titleCode, templateSelector, width, height, saveSuccessFunction) { function popupDialogWithFormView(getUrl, postUrl, submitType, titleCode, templateSelector, width, height, saveSuccessFunction) {
var dialogDiv = $("<div id='dialog-form'></div>"); var dialogDiv = $("<div id='dialog-form'></div>");
var jqxhr = $.ajax({ var jqxhr = $.ajax({
url: url, url: getUrl,
type: 'GET', type: 'GET',
contentType: 'application/json', contentType: 'application/json',
dataType: 'json', dataType: 'json',
cache: false, cache: false,
success: function(data, textStatus, jqXHR) { success: function(data, textStatus, jqXHR) {
console.log(data);
var formHtml = $(templateSelector).render(data); var formHtml = $(templateSelector).render(data);
dialogDiv.append(formHtml); dialogDiv.append(formHtml);
@@ -198,13 +229,16 @@ $(document).ready(function() {
$('#selectedItems option').each(function(i) { $('#selectedItems option').each(function(i) {
$(this).attr("selected", "selected"); $(this).attr("selected", "selected");
}); });
var form_data = $('#entityform').serialize(); var newFormData = JSON.stringify($('#entityform').serializeObject());
console.log(newFormData);
var jqxhr = $.ajax({ var jqxhr = $.ajax({
url: url, url: postUrl,
type: 'POST', type: submitType,
data: form_data, contentType: 'application/json',
dataType: 'json',
data: newFormData,
success: saveSuccessFunction, success: saveSuccessFunction,
error: function(jqXHR, textStatus, errorThrown) { error: function(jqXHR, textStatus, errorThrown) {
handleXhrError(jqXHR, textStatus, errorThrown, "#formErrorsTemplate", "#formerrors"); handleXhrError(jqXHR, textStatus, errorThrown, "#formErrorsTemplate", "#formerrors");
@@ -262,7 +296,8 @@ $(document).ready(function() {
$("#settings").html(tableHtml); $("#settings").html(tableHtml);
$('#changepassword').click(function(e) { $('#changepassword').click(function(e) {
var url = '${rootContext}org/admin/settings/password'; var getUrl = 'http://localhost:8080/mifosng-provider/api/v1/useraccounts/current/password/template';
var putUrl = 'http://localhost:8080/mifosng-provider/api/v1/useraccounts/current/password';
var templateSelector = "#changePasswordFormTemplate"; var templateSelector = "#changePasswordFormTemplate";
var width = 600; var width = 600;
var height = 350; var height = 350;
@@ -272,13 +307,13 @@ $(document).ready(function() {
$("#tabs").tabs('load', 0); $("#tabs").tabs('load', 0);
} }
popupDialogWithFormView(url, 'dialog.title.update.password', templateSelector, width, height, saveSuccessFunction); popupDialogWithFormView(getUrl, putUrl, 'PUT', 'dialog.title.update.password', templateSelector, width, height, saveSuccessFunction);
e.preventDefault(); e.preventDefault();
}); });
$('#changedetails').click(function(e) { $('#changedetails').click(function(e) {
var url = '${rootContext}org/admin/settings/details'; var getAndPutUrl = 'http://localhost:8080/mifosng-provider/api/v1/useraccounts/current';
var templateSelector = "#userSettingsFormTemplate"; var templateSelector = "#userSettingsFormTemplate";
var width = 600; var width = 600;
var height = 350; var height = 350;
@@ -288,7 +323,7 @@ $(document).ready(function() {
$("#tabs").tabs('load', 0); $("#tabs").tabs('load', 0);
} }
popupDialogWithFormView(url, 'dialog.title.update.details', templateSelector, width, height, saveSuccessFunction); popupDialogWithFormView(getAndPutUrl, getAndPutUrl, 'PUT', 'dialog.title.update.details', templateSelector, width, height, saveSuccessFunction);
e.preventDefault(); e.preventDefault();
}); });
@@ -309,9 +344,8 @@ $(document).ready(function() {
<div id="spacer" style="line-height: 15px;">&nbsp;</div> <div id="spacer" style="line-height: 15px;">&nbsp;</div>
<div id="content"> <div id="content">
<div id="tabs"> <div id="tabs">
<c:url value="/org/admin/settings/details" var="currentUserSettingsUrl" />
<ul> <ul>
<li><a href="${currentUserSettingsUrl}" title="settings"><spring:message code="tab.settings"/></a></li> <li><a href="http://localhost:8080/mifosng-provider/api/v1/useraccounts/current" title="settings"><spring:message code="tab.settings"/></a></li>
</ul> </ul>
<div id="settings"> <div id="settings">
</div> </div>
@@ -2,7 +2,6 @@ package org.mifosng.platform;
import org.mifosng.data.EntityIdentifier; import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.command.AdjustLoanTransactionCommand; import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.ChangePasswordCommand;
import org.mifosng.data.command.EnrollClientCommand; import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.data.command.LoanStateTransitionCommand; import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand; import org.mifosng.data.command.LoanTransactionCommand;
@@ -12,15 +11,10 @@ import org.mifosng.data.command.SubmitLoanApplicationCommand;
import org.mifosng.data.command.UndoLoanApprovalCommand; import org.mifosng.data.command.UndoLoanApprovalCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand; import org.mifosng.data.command.UndoLoanDisbursalCommand;
import org.mifosng.data.command.UpdateUsernamePasswordCommand; import org.mifosng.data.command.UpdateUsernamePasswordCommand;
import org.mifosng.data.command.UserCommand;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
public interface WritePlatformService { public interface WritePlatformService {
Long updateCurrentUser(UserCommand command);
Long updateCurrentUserPassword(ChangePasswordCommand command);
Long createRole(RoleCommand command); Long createRole(RoleCommand command);
Long updateRole(RoleCommand command); Long updateRole(RoleCommand command);
@@ -20,7 +20,6 @@ import org.mifosng.data.MoneyData;
import org.mifosng.data.ScheduledLoanInstallment; import org.mifosng.data.ScheduledLoanInstallment;
import org.mifosng.data.command.AdjustLoanTransactionCommand; import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.CalculateLoanScheduleCommand; import org.mifosng.data.command.CalculateLoanScheduleCommand;
import org.mifosng.data.command.ChangePasswordCommand;
import org.mifosng.data.command.EnrollClientCommand; import org.mifosng.data.command.EnrollClientCommand;
import org.mifosng.data.command.LoanStateTransitionCommand; import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand; import org.mifosng.data.command.LoanTransactionCommand;
@@ -30,7 +29,6 @@ import org.mifosng.data.command.SubmitLoanApplicationCommand;
import org.mifosng.data.command.UndoLoanApprovalCommand; import org.mifosng.data.command.UndoLoanApprovalCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand; import org.mifosng.data.command.UndoLoanDisbursalCommand;
import org.mifosng.data.command.UpdateUsernamePasswordCommand; import org.mifosng.data.command.UpdateUsernamePasswordCommand;
import org.mifosng.data.command.UserCommand;
import org.mifosng.platform.client.domain.Client; import org.mifosng.platform.client.domain.Client;
import org.mifosng.platform.client.domain.ClientRepository; import org.mifosng.platform.client.domain.ClientRepository;
import org.mifosng.platform.client.domain.Note; import org.mifosng.platform.client.domain.Note;
@@ -70,7 +68,6 @@ import org.mifosng.platform.user.domain.PermissionRepository;
import org.mifosng.platform.user.domain.PlatformUserRepository; import org.mifosng.platform.user.domain.PlatformUserRepository;
import org.mifosng.platform.user.domain.Role; import org.mifosng.platform.user.domain.Role;
import org.mifosng.platform.user.domain.RoleRepository; import org.mifosng.platform.user.domain.RoleRepository;
import org.mifosng.platform.user.service.UserCommandValidator;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@@ -92,7 +89,6 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
private final CalculationPlatformService calculationPlatformService; private final CalculationPlatformService calculationPlatformService;
private final RoleRepository roleRepository; private final RoleRepository roleRepository;
private final PermissionRepository permissionRepository; private final PermissionRepository permissionRepository;
private final AppUserRepository appUserRepository;
private final NoteRepository noteRepository; private final NoteRepository noteRepository;
private final LoanTransactionRepository loanTransactionRepository; private final LoanTransactionRepository loanTransactionRepository;
@@ -108,7 +104,6 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
final LoanTransactionRepository loanTransactionRepository, final LoanTransactionRepository loanTransactionRepository,
final LoanStatusRepository loanStatusRepository, final LoanStatusRepository loanStatusRepository,
final CalculationPlatformService calculationPlatformService, final CalculationPlatformService calculationPlatformService,
final AppUserRepository appUserRepository,
final RoleRepository roleRepository, final RoleRepository roleRepository,
final PermissionRepository permissionRepository) { final PermissionRepository permissionRepository) {
this.officeRepository = officeRepository; this.officeRepository = officeRepository;
@@ -121,50 +116,10 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
this.loanTransactionRepository = loanTransactionRepository; this.loanTransactionRepository = loanTransactionRepository;
this.loanStatusRepository = loanStatusRepository; this.loanStatusRepository = loanStatusRepository;
this.calculationPlatformService = calculationPlatformService; this.calculationPlatformService = calculationPlatformService;
this.appUserRepository = appUserRepository;
this.roleRepository = roleRepository; this.roleRepository = roleRepository;
this.permissionRepository = permissionRepository; this.permissionRepository = permissionRepository;
} }
@Transactional
@Override
public Long updateCurrentUser(UserCommand command) {
AppUser currentUser = extractAuthenticatedUser();
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 = extractAuthenticatedUser();
ChangePasswordCommandValidator validator = new ChangePasswordCommandValidator(command);
validator.validate();
AppUser userToUpdate = this.appUserRepository.findOne(currentUser.getId());
PlatformUser dummyPlatformUser = new BasicPasswordEncodablePlatformUser(
((AppUser) userToUpdate).getId(),
userToUpdate.getUsername(), command.getPassword());
String newPasswordEncoded = this.platformPasswordEncoder
.encode(dummyPlatformUser);
userToUpdate.updatePasswordOnFirstTimeLogin(newPasswordEncoded);
return userToUpdate.getId();
}
@Transactional @Transactional
@Override @Override
public Long createRole(final RoleCommand command) { public Long createRole(final RoleCommand command) {
@@ -0,0 +1,96 @@
package org.mifosng.platform.api.user;
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.ReadPlatformService;
import org.mifosng.platform.user.domain.AppUser;
import org.mifosng.platform.user.domain.AppUserRepository;
import org.mifosng.platform.user.service.AppUserWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
@Path("/v1/useraccounts")
@Component
@Scope("singleton")
public class UserAccountApiResource {
@Autowired
private ReadPlatformService readPlatformService;
@Autowired
private AppUserWritePlatformService appUserWritePlatformService;
@Autowired
private AppUserRepository appUserRepository;
private void hardcodeUserIntoSecurityContext() {
AppUser currentUser = this.appUserRepository.findOne(Long.valueOf(1));
Authentication auth = new UsernamePasswordAuthenticationToken(currentUser, currentUser, currentUser.getAuthorities());
SecurityContext context = SecurityContextHolder.getContext();
context.setAuthentication(auth);
}
@GET
@Path("current")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON})
public Response retrieveCurrentUser() {
hardcodeUserIntoSecurityContext();
AppUserData user = this.readPlatformService.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) {
hardcodeUserIntoSecurityContext();
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) {
hardcodeUserIntoSecurityContext();
Long userId = this.appUserWritePlatformService.updateCurrentUserPassword(command);
return Response.ok().entity(new EntityIdentifier(userId)).build();
}
}
@@ -15,7 +15,6 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import org.mifosng.data.AppUserData;
import org.mifosng.data.EntityIdentifier; import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.EnumOptionList; import org.mifosng.data.EnumOptionList;
import org.mifosng.data.EnumOptionReadModel; import org.mifosng.data.EnumOptionReadModel;
@@ -25,9 +24,7 @@ import org.mifosng.data.PermissionData;
import org.mifosng.data.PermissionList; import org.mifosng.data.PermissionList;
import org.mifosng.data.RoleData; import org.mifosng.data.RoleData;
import org.mifosng.data.RoleList; import org.mifosng.data.RoleList;
import org.mifosng.data.command.ChangePasswordCommand;
import org.mifosng.data.command.RoleCommand; import org.mifosng.data.command.RoleCommand;
import org.mifosng.data.command.UserCommand;
import org.mifosng.platform.ReadPlatformService; import org.mifosng.platform.ReadPlatformService;
import org.mifosng.platform.WritePlatformService; import org.mifosng.platform.WritePlatformService;
import org.mifosng.platform.exceptions.ApplicationDomainRuleException; import org.mifosng.platform.exceptions.ApplicationDomainRuleException;
@@ -35,7 +32,6 @@ import org.mifosng.platform.exceptions.NewDataValidationException;
import org.mifosng.platform.exceptions.UnAuthenticatedUserException; import org.mifosng.platform.exceptions.UnAuthenticatedUserException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -50,79 +46,6 @@ public class UserAdmistrationResource {
@Autowired @Autowired
private WritePlatformService writePlatformService; private WritePlatformService writePlatformService;
@GET
@Path("user/current")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response retrieveCurrentUser() {
try {
AppUserData user = this.readPlatformService.retrieveCurrentUser();
return Response.ok().entity(user).build();
} catch (UnAuthenticatedUserException e) {
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
} catch (AccessDeniedException e) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id");
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
} catch (ApplicationDomainRuleException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build());
} catch (NewDataValidationException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build());
}
}
@POST
@Path("user/current")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response updateCurrentUser(UserCommand command) {
try {
Long userId = this.writePlatformService.updateCurrentUser(command);
return Response.ok().entity(new EntityIdentifier(userId)).build();
} catch (UnAuthenticatedUserException e) {
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
} catch (AccessDeniedException e) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id");
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
} catch (ApplicationDomainRuleException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build());
} catch (NewDataValidationException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build());
} catch (DataIntegrityViolationException e) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.username.already.exists.in.organisation", "username", command.getUsername());
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
}
}
@POST
@Path("user/current/password")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response updateCurrentUserPassword(ChangePasswordCommand command) {
try {
Long userId = this.writePlatformService.updateCurrentUserPassword(command);
return Response.ok().entity(new EntityIdentifier(userId)).build();
} catch (UnAuthenticatedUserException e) {
throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build());
} catch (AccessDeniedException e) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id");
ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse));
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build());
} catch (ApplicationDomainRuleException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build());
} catch (NewDataValidationException e) {
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build());
}
}
@GET @GET
@Path("role/all") @Path("role/all")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@@ -1,5 +1,6 @@
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 {
@@ -9,4 +10,8 @@ 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,11 +9,16 @@ 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.ChangePasswordCommandValidator;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException; import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.mifosng.platform.exceptions.PlatformDataIntegrityException; import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
import org.mifosng.platform.exceptions.PlatformResourceNotFoundException; import org.mifosng.platform.exceptions.PlatformResourceNotFoundException;
import org.mifosng.platform.infrastructure.BasicPasswordEncodablePlatformUser;
import org.mifosng.platform.infrastructure.PlatformEmailSendException; import org.mifosng.platform.infrastructure.PlatformEmailSendException;
import org.mifosng.platform.infrastructure.PlatformPasswordEncoder;
import org.mifosng.platform.infrastructure.PlatformUser;
import org.mifosng.platform.organisation.domain.Office; import org.mifosng.platform.organisation.domain.Office;
import org.mifosng.platform.organisation.domain.OfficeRepository; import org.mifosng.platform.organisation.domain.OfficeRepository;
import org.mifosng.platform.security.PlatformSecurityContext; import org.mifosng.platform.security.PlatformSecurityContext;
@@ -35,19 +40,21 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit
private final static Logger logger = LoggerFactory.getLogger(AppUserWritePlatformServiceJpaRepositoryImpl.class); private final static Logger logger = LoggerFactory.getLogger(AppUserWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final UserDomainService userDomainService;
private final PlatformPasswordEncoder platformPasswordEncoder;
private final AppUserRepository appUserRepository; private final AppUserRepository appUserRepository;
private final OfficeRepository officeRepository; private final OfficeRepository officeRepository;
private final RoleRepository roleRepository; private final RoleRepository roleRepository;
private final UserDomainService userDomainService;
@Autowired @Autowired
public AppUserWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final AppUserRepository appUserRepository, final UserDomainService userDomainService, public AppUserWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final AppUserRepository appUserRepository, final UserDomainService userDomainService,
final OfficeRepository officeRepository, final RoleRepository roleRepository) { final OfficeRepository officeRepository, final RoleRepository roleRepository, final PlatformPasswordEncoder platformPasswordEncoder) {
this.context = context; this.context = context;
this.appUserRepository = appUserRepository; this.appUserRepository = appUserRepository;
this.userDomainService = userDomainService; this.userDomainService = userDomainService;
this.officeRepository = officeRepository; this.officeRepository = officeRepository;
this.roleRepository = roleRepository; this.roleRepository = roleRepository;
this.platformPasswordEncoder = platformPasswordEncoder;
} }
@Transactional @Transactional
@@ -142,6 +149,44 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit
public void deleteUser(Long userId) { public void deleteUser(Long userId) {
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(
((AppUser) 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.