diff --git a/mifosng-data/src/main/java/org/mifosng/data/command/UserCommand.java b/mifosng-data/src/main/java/org/mifosng/data/command/UserCommand.java index 0a1627729..6e7b09ce9 100644 --- a/mifosng-data/src/main/java/org/mifosng/data/command/UserCommand.java +++ b/mifosng-data/src/main/java/org/mifosng/data/command/UserCommand.java @@ -1,12 +1,16 @@ package org.mifosng.data.command; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + import javax.xml.bind.annotation.XmlRootElement; /** * create or update user details command. */ @XmlRootElement -public class UserCommand { +public class UserCommand implements Serializable { private Long id; private String username; @@ -14,40 +18,15 @@ public class UserCommand { private String lastname; private String password; private String email; - private String[] roleIds; private Long officeId; + + private List notSelectedItems = new ArrayList(); + private List selectedItems = new ArrayList(); public UserCommand() { // } - public UserCommand(final String username, final String firstname, final String lastname, final String password, - final String email, final String[] roleIds, final Long officeId) { - this.username = username; - this.firstname = firstname; - this.lastname = lastname; - this.password = password; - this.email = email; - this.roleIds = roleIds; - this.officeId = officeId; - } - - public UserCommand(final String username, final String firstname, final String lastname, final String email) { - this.username = username; - this.firstname = firstname; - this.lastname = lastname; - this.email = email; - } - - public UserCommand(final String username, final String password, - final String email, final String[] roleIds, final Long officeId) { - this.username = username; - this.password = password; - this.email = email; - this.roleIds = roleIds; - this.officeId = officeId; - } - public String getDisplayName() { return new StringBuilder(this.lastname).append(", ").append(this.firstname).toString(); } @@ -76,14 +55,6 @@ public class UserCommand { this.email = email; } - public String[] getRoleIds() { - return this.roleIds; - } - - public void setRoleIds(final String[] roleIds) { - this.roleIds = roleIds; - } - public Long getOfficeId() { return this.officeId; } @@ -115,4 +86,20 @@ public class UserCommand { public void setId(Long id) { this.id = id; } + + public List getNotSelectedItems() { + return notSelectedItems; + } + + public void setNotSelectedItems(List notSelectedItems) { + this.notSelectedItems = notSelectedItems; + } + + public List getSelectedItems() { + return selectedItems; + } + + public void setSelectedItems(List selectedItems) { + this.selectedItems = selectedItems; + } } \ No newline at end of file diff --git a/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/CommonRestOperations.java b/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/CommonRestOperations.java index 8373fe62f..df208ae9a 100644 --- a/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/CommonRestOperations.java +++ b/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/CommonRestOperations.java @@ -33,25 +33,12 @@ public interface CommonRestOperations { void logout(String accessToken); - void updateProtectedResource( - ProtectedResourceDetails loadProtectedResourceDetailsById); - - Collection retrieveAllUsers(); - - AppUserData retrieveNewUserDetails(); - - AppUserData retrieveUser(Long userId); + void updateProtectedResource(ProtectedResourceDetails loadProtectedResourceDetailsById); AppUserData retrieveCurrentUser(); - EntityIdentifier createUser(UserCommand command); - - EntityIdentifier updateUser(UserCommand command); - EntityIdentifier updateCurrentUserPassword(ChangePasswordCommand command); - void deleteUser(Long userId); - Collection retrieveAllRoles(); RoleData retrieveRole(Long roleId); diff --git a/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/CommonRestOperationsImpl.java b/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/CommonRestOperationsImpl.java index b90ada836..1a0b2c41d 100644 --- a/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/CommonRestOperationsImpl.java +++ b/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/CommonRestOperationsImpl.java @@ -27,7 +27,6 @@ import org.mifosng.data.PermissionData; import org.mifosng.data.PermissionList; import org.mifosng.data.RoleData; import org.mifosng.data.RoleList; -import org.mifosng.data.UserList; import org.mifosng.data.command.AdjustLoanTransactionCommand; import org.mifosng.data.command.CalculateLoanScheduleCommand; import org.mifosng.data.command.ChangePasswordCommand; @@ -531,41 +530,6 @@ public class CommonRestOperationsImpl implements CommonRestOperations { requestHeaders); } - @Override - public EntityIdentifier createUser(final UserCommand command) { - try { - URI restUri = URI.create(getBaseServerUrl().concat( - "api/protected/admin/user/new")); - - ResponseEntity s = this.oauthRestServiceTemplate - .postForEntity(restUri, createUserRequest(command), - EntityIdentifier.class); - - return s.getBody(); - } catch (HttpStatusCodeException e) { - ErrorResponseList errorList = parseErrors(e); - throw new ClientValidationException(errorList.getErrors()); - } - } - - @Override - public EntityIdentifier updateUser(UserCommand command) { - try { - URI restUri = URI.create(getBaseServerUrl().concat( - "api/protected/admin/user/").concat( - command.getId().toString())); - - ResponseEntity s = this.oauthRestServiceTemplate - .postForEntity(restUri, createUserRequest(command), - EntityIdentifier.class); - - return s.getBody(); - } catch (HttpStatusCodeException e) { - ErrorResponseList errorList = parseErrors(e); - throw new ClientValidationException(errorList.getErrors()); - } - } - @Override public EntityIdentifier updateCurrentUserDetails(UserCommand command) { try { @@ -602,14 +566,6 @@ public class CommonRestOperationsImpl implements CommonRestOperations { } } - @Override - public void deleteUser(Long userId) { - URI restUri = URI.create(getBaseServerUrl().concat( - "api/protected/admin/user/").concat(userId.toString())); - - this.oauthRestServiceTemplate.delete(restUri); - } - private HttpEntity createUserRequest(final UserCommand command) { HttpHeaders requestHeaders = new HttpHeaders(); @@ -644,46 +600,6 @@ public class CommonRestOperationsImpl implements CommonRestOperations { return requestEntity; } - @Override - public Collection retrieveAllUsers() { - try { - URI restUri = URI.create(getBaseServerUrl().concat( - "api/protected/admin/user/all")); - - ResponseEntity s = this.oauthRestServiceTemplate - .exchange(restUri, HttpMethod.GET, emptyRequest(), - UserList.class); - - return s.getBody().getUsers(); - } catch (HttpStatusCodeException e) { - ErrorResponseList errorList = parseErrors(e); - throw new ClientValidationException(errorList.getErrors()); - } - } - - @Override - public AppUserData retrieveNewUserDetails() { - - URI restUri = URI.create(getBaseServerUrl().concat( - "api/protected/admin/user/new")); - - ResponseEntity s = this.oauthRestServiceTemplate.exchange( - restUri, HttpMethod.GET, emptyRequest(), AppUserData.class); - - return s.getBody(); - } - - @Override - public AppUserData retrieveUser(Long userId) { - URI restUri = URI.create(getBaseServerUrl().concat( - "api/protected/admin/user/").concat(userId.toString())); - - ResponseEntity s = this.oauthRestServiceTemplate.exchange( - restUri, HttpMethod.GET, emptyRequest(), AppUserData.class); - - return s.getBody(); - } - @Override public AppUserData retrieveCurrentUser() { URI restUri = URI.create(getBaseServerUrl().concat( diff --git a/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/admin/AdministrationController.java b/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/admin/AdministrationController.java index ff0c4d9c7..c332129b7 100644 --- a/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/admin/AdministrationController.java +++ b/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/admin/AdministrationController.java @@ -78,7 +78,11 @@ public class AdministrationController { @RequestParam(value="lastname", required=false) String lastname, @RequestParam(value="email", required=false) String email) { - UserCommand command = new UserCommand(username, firstname, lastname, email); + UserCommand command = new UserCommand(); + command.setUsername(username); + command.setFirstname(firstname); + command.setLastname(lastname); + command.setEmail(email); return this.commonRestOperations.updateCurrentUserDetails(command); } diff --git a/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/user/AppUserController.java b/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/user/AppUserController.java index d72959e23..11d9415a2 100644 --- a/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/user/AppUserController.java +++ b/mifosng-individual-lending-app/src/main/java/org/mifosng/ui/user/AppUserController.java @@ -4,13 +4,11 @@ import java.util.Collection; import javax.servlet.http.HttpServletResponse; -import org.mifosng.data.AppUserData; import org.mifosng.data.EntityIdentifier; import org.mifosng.data.ErrorResponse; import org.mifosng.data.PermissionData; import org.mifosng.data.RoleData; import org.mifosng.data.command.RoleCommand; -import org.mifosng.data.command.UserCommand; import org.mifosng.ui.CommonRestOperations; import org.mifosng.ui.loanproduct.ClientValidationException; import org.springframework.beans.factory.annotation.Autowired; @@ -83,63 +81,6 @@ public class AppUserController { return this.commonRestOperations.updateRole(command); } - @RequestMapping(consumes="application/json", produces="application/json", value = "/admin/user/all", method = RequestMethod.GET) - public @ResponseBody Collection viewAllUsers() { - - return this.commonRestOperations.retrieveAllUsers(); - } - - @RequestMapping(consumes="application/json", produces="application/json", value = "/admin/user/new", method = RequestMethod.GET) - public @ResponseBody AppUserData viewUser() { - - return this.commonRestOperations.retrieveNewUserDetails(); - } - - @RequestMapping(consumes="application/x-www-form-urlencoded", produces="application/json", value = "/admin/user/new", method = RequestMethod.POST) - @ResponseStatus(HttpStatus.OK) - public @ResponseBody EntityIdentifier createNewUser(@RequestParam(value="selectedItems", required=false) String[] selectedRoles, - @RequestParam(value="username") String username, - @RequestParam(value="firstname") String firstname, - @RequestParam(value="lastname") String lastname, - @RequestParam(value="email") String email, - @RequestParam(value="officeId") Long officeId) { - - UserCommand command = new UserCommand(username, firstname, lastname, "", email, selectedRoles, officeId); - - return this.commonRestOperations.createUser(command); - } - - @RequestMapping(consumes = "application/json", produces = "application/json", value = "/admin/user/{userId}", method = RequestMethod.DELETE) - public @ResponseBody - EntityIdentifier attemptToDeleteUser(@PathVariable("userId") Long userId) { - - this.commonRestOperations.deleteUser(userId); - - return new EntityIdentifier(Long.valueOf(1)); - } - - @RequestMapping(consumes="application/json", produces="application/json", value = "/admin/user/{userId}", method = RequestMethod.GET) - public @ResponseBody AppUserData viewUser(@PathVariable("userId") Long userId) { - - return this.commonRestOperations.retrieveUser(userId); - } - - @RequestMapping(consumes="application/x-www-form-urlencoded", produces="application/json", value = "/admin/user/{userId}", method = RequestMethod.POST) - @ResponseStatus(HttpStatus.OK) - public @ResponseBody EntityIdentifier updateUser(@PathVariable("userId") Long userId, - @RequestParam(value="selectedItems", required=false) String[] selectedRoles, - @RequestParam(value="username") String username, - @RequestParam(value="firstname") String firstname, - @RequestParam(value="lastname") String lastname, - @RequestParam(value="email") String email, - @RequestParam(value="officeId") Long officeId) { - - UserCommand command = new UserCommand(username, firstname, lastname, "", email, selectedRoles, officeId); - command.setId(userId); - - return this.commonRestOperations.updateUser(command); - } - @ExceptionHandler(ClientValidationException.class) public @ResponseBody Collection validationException(ClientValidationException ex, HttpServletResponse response) { diff --git a/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/admin/orghome.jsp b/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/admin/orghome.jsp index d8b6a7c6f..9a9243810 100644 --- a/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/admin/orghome.jsp +++ b/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/admin/orghome.jsp @@ -220,13 +220,10 @@ $('#selectedItems option').each(function(i) { $(this).attr("selected", "selected"); }); - var newFormData = JSON.stringify($('#entityform').serializeObject()); console.log(newFormData); - var form_data = $('#entityform').serialize(); - var jqxhr = $.ajax({ url: postUrl, type: submitType, diff --git a/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/admin/userhome.jsp b/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/admin/userhome.jsp index ee7526055..47dd581a6 100644 --- a/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/admin/userhome.jsp +++ b/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/admin/userhome.jsp @@ -55,9 +55,9 @@ $(document).ready(function() { return false; } }, - globalDate: function(dateParts) { + globalDate: function(localDateAsISOString) { try { - + var dateParts = localDateAsISOString.split("-") var year = dateParts[0]; var month = parseInt(dateParts[1]) - 1; // month is zero indexed var day = dateParts[2]; @@ -70,9 +70,9 @@ $(document).ready(function() { return "??"; } }, - globalDateTime: function(dateParts) { + globalDateTime: function(dateInMillis) { try { - var d = new Date(dateParts); + var d = new Date(dateInMillis); return Globalize.format(d,"F"); } catch(e) { @@ -114,17 +114,28 @@ $(document).ready(function() { removeErrors(placeholderDiv); var jsonErrors = JSON.parse(jqXHR.responseText); - + console.log(jsonErrors); + var valErrors = jsonErrors.errors; + console.log(valErrors); var errorArray = new Array(); var arrayIndex = 0; - $.each(jsonErrors, function() { - var fieldId = '#' + this.field; + $.each(valErrors, function() { + var fieldId = '#' + this.parameterName; $(fieldId).addClass("ui-state-error"); var errorObj = new Object(); - errorObj.field = this.field; - errorObj.code = this.code; - errorObj.message = jQuery.i18n.prop(this.code, this.args); + errorObj.field = this.parameterName; + errorObj.code = this.userMessageGlobalisationCode; + + var argArray = new Array(); + var argArrayIndex = 0; + $.each(this.args, function() { + argArray[argArrayIndex] = this.value; + argArrayIndex++; + }); + console.log(argArray); + // 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; errorArray[arrayIndex] = errorObj; @@ -144,17 +155,33 @@ $(document).ready(function() { } } - function popupDialogWithFormView(url, titleCode, templateSelector, width, height, saveSuccessFunction) { + $.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 { + o[this.name] = this.value || ''; + } + }); + return o; + }; + + function popupDialogWithFormView(getUrl, postUrl, submitType, titleCode, templateSelector, width, height, saveSuccessFunction) { var dialogDiv = $("
"); - var jqxhr = $.ajax({ - url: url, + url: getUrl, type: 'GET', contentType: 'application/json', dataType: 'json', cache: false, success: function(data, textStatus, jqXHR) { - + console.log(data); var formHtml = $(templateSelector).render(data); dialogDiv.append(formHtml); @@ -173,17 +200,20 @@ $(document).ready(function() { $(this).attr("selected", "selected"); }); - var form_data = $('#entityform').serialize(); - + + var newFormData = JSON.stringify($('#entityform').serializeObject()); + console.log(newFormData); + var jqxhr = $.ajax({ - url: url, - type: 'POST', - data: form_data, - success: saveSuccessFunction - }); - - jqxhr.error(function(jqXHR, textStatus, errorThrown) { - handleXhrError(jqXHR, textStatus, errorThrown, "#formErrorsTemplate", "#formerrors"); + url: postUrl, + type: submitType, + contentType: 'application/json', + dataType: 'json', + data: newFormData, + success: saveSuccessFunction, + error: function(jqXHR, textStatus, errorThrown) { + handleXhrError(jqXHR, textStatus, errorThrown, "#formErrorsTemplate", "#formerrors"); + } }); }; @@ -197,7 +227,7 @@ $(document).ready(function() { buttons: buttonsOpts, close: function() { // if i dont do this, theres a problem with errors being appended to dialog view second time round - $(this).dialog("destroy").remove(); + $(this).remove(); }, open: function (event, ui) { @@ -232,11 +262,8 @@ $(document).ready(function() { dataType: 'json', cache: false, success: function(data, textStatus, jqXHR) { - - var tableObj = new Object(); - tableObj.items = data; - - var tableHtml = $(templateSelector).render(tableObj); + console.log(data); + var tableHtml = $(templateSelector).render(data); $(displayAreaDivSelector).html(""); $(displayAreaDivSelector).html(tableHtml); @@ -248,7 +275,7 @@ $(document).ready(function() { var width = 1000; var height = 550; - popupDialogWithFormView(url, 'dialog.title.edit.details', singleEntityTemplateSelector, width, height, saveSuccessFunction); + popupDialogWithFormView(url, url, 'PUT', 'dialog.title.edit.details', singleEntityTemplateSelector, width, height, saveSuccessFunction); e.preventDefault(); }); @@ -295,46 +322,24 @@ $(document).ready(function() { } $('#listusers').click(function(e) { - var listUrl = "${allUsersUrl}"; - var templateSelector = "#usersListTemplate"; - var displayAreaDivSelector = "#contentplaceholder"; - var singleEntityPrefixUrl = '${rootContext}admin/user/'; - var singleEntityTemplateSelector = "#userFormTemplate"; - - var saveSuccessFunction = function(data, textStatus, jqXHR) { - $("#dialog-form").dialog("destroy").remove(); - var listUrl = "${allUsersUrl}"; - var templateSelector = "#usersListTemplate"; - var displayAreaDivSelector = "#contentplaceholder"; - var singleEntityPrefixUrl = '${rootContext}admin/user/'; - var singleEntityTemplateSelector = "#userFormTemplate"; - - displayListView(listUrl, templateSelector, displayAreaDivSelector, singleEntityPrefixUrl, singleEntityTemplateSelector); - } - - displayListView(listUrl, templateSelector, displayAreaDivSelector, singleEntityPrefixUrl, singleEntityTemplateSelector, saveSuccessFunction); - + var listUrl = "http://localhost:8085/mifosng-provider/api/v1/users"; + refreshUsersView(); e.preventDefault(); }); $('#adduser').click(function(e) { - var url = '${rootContext}admin/user/new'; + var url = 'http://localhost:8085/mifosng-provider/api/v1/users/template'; + var postUrl = "http://localhost:8085/mifosng-provider/api/v1/users"; var templateSelector = "#userFormTemplate"; var width = 1000; var height = 550; var saveSuccessFunction = function(data, textStatus, jqXHR) { - $("#dialog-form").dialog("close"); - var listUrl = "${allUsersUrl}"; - var templateSelector = "#usersListTemplate"; - var displayAreaDivSelector = "#contentplaceholder"; - var singleEntityPrefixUrl = '${rootContext}admin/user/'; - var singleEntityTemplateSelector = "#userFormTemplate"; - - displayListView(listUrl, templateSelector, displayAreaDivSelector, singleEntityPrefixUrl, singleEntityTemplateSelector); + $("#dialog-form").dialog("close"); + refreshUsersView(); } - popupDialogWithFormView(url, 'dialog.title.add.user', templateSelector, width, height, saveSuccessFunction); + popupDialogWithFormView(url, postUrl, 'POST', 'dialog.title.add.user', templateSelector, width, height, saveSuccessFunction); e.preventDefault(); }); @@ -397,6 +402,71 @@ $(document).ready(function() { e.preventDefault(); }); + + function refreshUsersView() { + + var listUrl = 'http://localhost:8085/mifosng-provider/api/v1/users'; + var templateSelector = "#usersListTemplate"; + var displayAreaDivSelector = "#contentplaceholder"; + var singleEntityPrefixUrl = 'http://localhost:8085/mifosng-provider/api/v1/users/'; + var singleEntityTemplateSelector = "#userFormTemplate"; + + var jqxhr = $.ajax({ + url: listUrl, + type: 'GET', + contentType: 'application/json', + dataType: 'json', + success: function(data, textStatus, jqXHR) { + console.log(data); + var officeListHtml = $(templateSelector).render(data); + $(displayAreaDivSelector).html(officeListHtml); + + $("a.edit").click( function(e) { + var linkId = this.id; + var entityId = linkId.replace("edit", ""); + var getUrl = 'http://localhost:8085/mifosng-provider/api/v1/users/' + entityId; + var putUrl = 'http://localhost:8085/mifosng-provider/api/v1/users/' + entityId; + + var templateSelector = "#userFormTemplate"; + var width = 600; + var height = 400; + + var saveSuccessFunction = function(data, textStatus, jqXHR) { + $("#dialog-form").dialog("close"); + refreshUsersView(); + } + + popupDialogWithFormView(getUrl, putUrl, 'PUT', "dialog.title.edit.details", templateSelector, width, height, saveSuccessFunction); + e.preventDefault(); + }); + + $("a.delete").click( function(e) { + var linkId = this.id; + var entityId = linkId.replace("delete", ""); + var url = 'http://localhost:8085/mifosng-provider/api/v1/users/' + entityId; + showNotAvailableDialog('dialog.title.functionality.not.available'); + + e.preventDefault(); + }); + + var oTable = $("#entitytable").dataTable( { + "bSort": true, + "bInfo": true, + "bJQueryUI": true, + "bRetrieve": false, + "bScrollCollapse": false, + "bPaginate": false, + "bLengthChange": false, + "bFilter": false, + "bAutoWidth": false, + } ); + } + }); + + jqxhr.error(function(jqXHR, textStatus, errorThrown) { + handleXhrError(jqXHR, textStatus, errorThrown, "#formErrorsTemplate", "#formerrors"); + }); + } // end of document.ready }); diff --git a/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/administration-view-templates.jsp b/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/administration-view-templates.jsp index 55b705b98..7a2beadfa 100644 --- a/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/administration-view-templates.jsp +++ b/mifosng-individual-lending-app/src/main/webapp/WEB-INF/views/administration-view-templates.jsp @@ -440,7 +440,7 @@ -{{#each items}} +{{#each users}} {{=officeName}} {{=username}} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformServiceImpl.java index 5b57a3552..3cf6ade6a 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/ReadPlatformServiceImpl.java @@ -760,11 +760,13 @@ public class ReadPlatformServiceImpl implements ReadPlatformService { List offices = retrieveOffices(); - List availableRoles = new ArrayList( - retrieveAllRoles()); + List availableRoles = new ArrayList(retrieveAllRoles()); - AppUser user = this.appUserRepository.findOne(usersThatMatch( - currentUser.getOrganisation(), userId)); + AppUser user = this.appUserRepository.findOne(usersThatMatch(currentUser.getOrganisation(), userId)); + + if (user == null) { + throw new PlatformResourceNotFoundException("error.msg.user.id.invalid", "User with identifier {0} does not exist.", userId); + } List userRoleData = new ArrayList(); Set userRoles = user.getRoles(); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/UserValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/UserCommandValidator.java similarity index 94% rename from mifosng-provider/src/main/java/org/mifosng/platform/UserValidator.java rename to mifosng-provider/src/main/java/org/mifosng/platform/UserCommandValidator.java index c5e3c8b49..b86e21696 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/UserValidator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/UserCommandValidator.java @@ -8,11 +8,11 @@ import org.mifosng.data.ErrorResponse; import org.mifosng.data.command.UserCommand; import org.mifosng.platform.exceptions.NewDataValidationException; -public class UserValidator { +public class UserCommandValidator { private final UserCommand command; - public UserValidator(UserCommand command) { + public UserCommandValidator(UserCommand command) { this.command = command; } @@ -27,7 +27,7 @@ public class UserValidator { dataValidationErrors.add(error); } - if (command.getRoleIds() == null) { + if (command.getSelectedItems() == null) { ErrorResponse error = new ErrorResponse("validation.msg.user.roles.cannot.be.blank", "selectedItems"); dataValidationErrors.add(error); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/WritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/WritePlatformServiceJpaRepositoryImpl.java index c0dbbde82..0977d4558 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/WritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/WritePlatformServiceJpaRepositoryImpl.java @@ -15,6 +15,7 @@ import java.util.Set; import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDate; +import org.mifosng.data.ApiParameterError; import org.mifosng.data.EntityIdentifier; import org.mifosng.data.ErrorResponse; import org.mifosng.data.LoanSchedule; @@ -42,8 +43,10 @@ import org.mifosng.platform.currency.domain.MonetaryCurrency; import org.mifosng.platform.currency.domain.Money; import org.mifosng.platform.exceptions.ApplicationDomainRuleException; import org.mifosng.platform.exceptions.InvalidSignupException; -import org.mifosng.platform.exceptions.NewDataValidationException; import org.mifosng.platform.exceptions.NoAuthorizationException; +import org.mifosng.platform.exceptions.PlatformApiDataValidationException; +import org.mifosng.platform.exceptions.PlatformDataIntegrityException; +import org.mifosng.platform.exceptions.PlatformResourceNotFoundException; import org.mifosng.platform.exceptions.UnAuthenticatedUserException; import org.mifosng.platform.infrastructure.BasicPasswordEncodablePlatformUser; import org.mifosng.platform.infrastructure.PlatformPasswordEncoder; @@ -147,11 +150,11 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi try { AppUser currentUser = extractAuthenticatedUser(); - UserValidator validator = new UserValidator(command); + UserCommandValidator validator = new UserCommandValidator(command); validator.validate(); Set allRoles = new HashSet(); - for (String roleId : command.getRoleIds()) { + for (String roleId : command.getSelectedItems()) { Role role = this.roleRepository.findOne(Long.valueOf(roleId)); allRoles.add(role); } @@ -173,36 +176,42 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi @Transactional @Override public Long updateUser(UserCommand command) { + try { AppUser currentUser = extractAuthenticatedUser(); - UserValidator validator = new UserValidator(command); + UserCommandValidator validator = new UserCommandValidator(command); validator.validate(); - List dataValidationErrors = new ArrayList(); + List dataValidationErrors = new ArrayList(); if (command.getId() == null) { - ErrorResponse error = new ErrorResponse("validation.msg.user.id.cannot.be.blank", "id"); + ApiParameterError error = ApiParameterError.parameterError("validation.msg.user.id.cannot.be.blank", "The parameter id cannot be empty.", "id"); dataValidationErrors.add(error); - } - - if (!dataValidationErrors.isEmpty()) { - throw new NewDataValidationException(dataValidationErrors, "Data validation error exist."); + + throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); } Set allRoles = new HashSet(); - for (String roleId : command.getRoleIds()) { + for (String roleId : command.getSelectedItems()) { Role role = this.roleRepository.findOne(Long.valueOf(roleId)); allRoles.add(role); } Office 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())); + if (userToUpdate == null) { + throw new PlatformResourceNotFoundException("error.msg.user.id.invalid", "User with identifier {0} does not exist.", command.getId()); + } + userToUpdate.update(allRoles, office, command.getUsername(), command.getFirstname(), command.getLastname(), command.getEmail()); return userToUpdate.getId(); } catch (DataIntegrityViolationException e) { - throw new UsernameAlreadyExistsException(e); + throw new PlatformDataIntegrityException("validation.msg.username.already.exists.in.organisation", "Username already exists.", "username", command.getUsername()); } } @@ -211,7 +220,7 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi public Long updateCurrentUser(UserCommand command) { AppUser currentUser = extractAuthenticatedUser(); - UserValidator validator = new UserValidator(command); + UserCommandValidator validator = new UserCommandValidator(command); validator.validateAccountSettingDetails(); AppUser userToUpdate = this.appUserRepository.findOne(currentUser.getId()); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/user/UserApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/user/UserApiResource.java new file mode 100644 index 000000000..748387b15 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/user/UserApiResource.java @@ -0,0 +1,257 @@ +package org.mifosng.platform.api.user; + +import java.util.Arrays; +import java.util.Collection; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.mifosng.data.AppUserData; +import org.mifosng.data.EntityIdentifier; +import org.mifosng.data.ErrorResponse; +import org.mifosng.data.ErrorResponseList; +import org.mifosng.data.UserList; +import org.mifosng.data.command.ChangePasswordCommand; +import org.mifosng.data.command.UserCommand; +import org.mifosng.platform.ReadPlatformService; +import org.mifosng.platform.WritePlatformService; +import org.mifosng.platform.exceptions.ApplicationDomainRuleException; +import org.mifosng.platform.exceptions.NewDataValidationException; +import org.mifosng.platform.exceptions.UnAuthenticatedUserException; +import org.mifosng.platform.user.domain.AppUser; +import org.mifosng.platform.user.domain.AppUserRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.security.access.AccessDeniedException; +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/users") +@Component +@Scope("singleton") +public class UserApiResource { + + private final static Logger logger = LoggerFactory.getLogger(UserApiResource.class); + + @Autowired + private ReadPlatformService readPlatformService; + + @Autowired + private WritePlatformService writePlatformService; + + @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 + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON}) + public Response retrieveUsers() { + + hardcodeUserIntoSecurityContext(); + + Collection users = this.readPlatformService.retrieveAllUsers(); + + return Response.ok().entity(new UserList(users)).build(); + } + + @GET + @Path("{userId}") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({ MediaType.APPLICATION_JSON}) + public Response retrieveUser(@PathParam("userId") final Long userId) { + + hardcodeUserIntoSecurityContext(); + + AppUserData user = this.readPlatformService.retrieveUser(userId); + + return Response.ok().entity(user).build(); + } + + @GET + @Path("template") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({ MediaType.APPLICATION_JSON}) + public Response newUserDetails() { + + hardcodeUserIntoSecurityContext(); + AppUserData newUser = this.readPlatformService.retrieveNewUserDetails(); + + return Response.ok().entity(newUser).build(); + } + + @POST + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({ MediaType.APPLICATION_JSON}) + public Response createUser(@Context HttpServletRequest request) { + +// try { + String selectedItems = request.getParameter("selectedItems"); + final UserCommand command = new UserCommand(); +// command.setSelectedItems(Arrays.asList(a)); + + hardcodeUserIntoSecurityContext(); + Long userId = this.writePlatformService.createUser(command); + return Response.ok().entity(new EntityIdentifier(userId)).build(); +// } catch (UsernameAlreadyExistsException e) { +// List allErrors = new ArrayList(); +// ErrorResponse err = new ErrorResponse("validation.msg.username.already.exists.in.organisation", "username", command.getUsername()); +// allErrors.add(err); +// +// throw new WebApplicationException(Response +// .status(Status.BAD_REQUEST) +// .entity(new ErrorResponseList(allErrors)).build()); +// } catch (PlatformEmailSendException e) { +// List allErrors = new ArrayList(); +// ErrorResponse err = new ErrorResponse("error.msg.user.email.invalid","email", "Email is invalid."); +// allErrors.add(err); +// throw new WebApplicationException(Response +// .status(Status.BAD_REQUEST) +// .entity(new ErrorResponseList(allErrors)).build()); +// } + } + + @DELETE + @Path("{userId}") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({ MediaType.APPLICATION_JSON}) + public Response deleteUser(@PathParam("userId") final Long userId) { + + try { + this.writePlatformService.deleteUser(userId); + + return Response.ok().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()); + } + } + + @PUT + @Path("{userId}") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({ MediaType.APPLICATION_JSON}) + public Response updateUser(@PathParam("userId") final Long userId, UserCommand command) { + + hardcodeUserIntoSecurityContext(); + +// UserCommand command = new UserCommand(); +// command.setSelectedItems(new ArrayList(commandEile.getSelectedItems())); + command.setId(userId); + + this.writePlatformService.updateUser(command); + + return Response.ok().entity(new EntityIdentifier(userId)).build(); + } + + @GET + @Path("user/current") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({ MediaType.APPLICATION_JSON}) + public Response retrieveCurrentUser() { + + try { + hardcodeUserIntoSecurityContext(); + + 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 { + hardcodeUserIntoSecurityContext(); + + 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 { + hardcodeUserIntoSecurityContext(); + + 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()); + } + } +} \ No newline at end of file