This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository coselmar. See http://git.codelutin.com/coselmar.git commit c8a14d839be2ed6d81bbbc07634e89fe940616a0 Author: Yannick Martel <martel@©odelutin.com> Date: Tue Nov 25 17:59:30 2014 +0100 #6014 add way to modify user (as admin and as user for its own account) in UI --- .../coselmar/services/v1/UsersWebService.java | 47 ++++++++--- coselmar-rest/src/main/resources/mapping | 4 +- coselmar-ui/src/main/webapp/index.html | 2 +- .../src/main/webapp/js/coselmar-controllers.js | 30 ++++++- .../src/main/webapp/js/coselmar-user-services.js | 26 +++++- .../src/main/webapp/views/users/edituser.html | 94 ++++++++++++++++++++++ .../src/main/webapp/views/users/newuser.html | 61 +------------- coselmar-ui/src/main/webapp/views/users/user.html | 14 +++- coselmar-ui/src/main/webapp/views/users/users.html | 4 +- 9 files changed, 200 insertions(+), 82 deletions(-) diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UsersWebService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UsersWebService.java index e837cbd..ecd02d2 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UsersWebService.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UsersWebService.java @@ -98,6 +98,7 @@ public class UsersWebService extends CoselmarWebServiceSupport { userEntity.setMail(mail); userEntity.setRole(CoselmarUserRole.valueOf(user.getRole().toUpperCase())); userEntity.setQualification(user.getQualification()); + userEntity.setOrganization(user.getOrganization()); String password = user.getPassword(); if (StringUtils.isBlank(password)) { @@ -131,12 +132,12 @@ public class UsersWebService extends CoselmarWebServiceSupport { String userId = user.getId(); if (StringUtils.isBlank(userId)) { - throw new InvalidParameterException("User.id is mandaotry"); + throw new InvalidParameterException("User.id is mandatory"); } // Admin does not need to give password, he should not know it anyway ! if (StringUtils.isBlank(user.getPassword()) && !isAdmin) { - throw new InvalidParameterException("User.password is mandaotry"); + throw new InvalidParameterException("User.password is mandatory"); } // Who is allowed here ? Admin and user himself only @@ -153,7 +154,12 @@ public class UsersWebService extends CoselmarWebServiceSupport { getPersistenceContext().getTopiaIdFactory().getSeparator() + userId; CoselmarUser coselmarUser = getCoselmarUserDao().forTopiaIdEquals(fullId).findAny(); - // Ok, let's start the user update ! + // Last check : the password + if (!isAdmin) { + checkPassword(coselmarUser.getPassword(), coselmarUser.getSalt(), user.getPassword()); + } + + // Ok, now let's start the user update ! // start with mail : should be unique String mail = user.getMail(); @@ -166,7 +172,7 @@ public class UsersWebService extends CoselmarWebServiceSupport { if (StringUtils.isNotBlank(firstName)) { coselmarUser.setFirstname(firstName); } else { - user.setOrganization(coselmarUser.getFirstname()); + user.setFirstName(coselmarUser.getFirstname()); } String userName = user.getName(); @@ -178,8 +184,8 @@ public class UsersWebService extends CoselmarWebServiceSupport { } String userRole = user.getRole(); - if (StringUtils.isNotBlank(userRole)) { - coselmarUser.setRole(CoselmarUserRole.valueOf(userName.toUpperCase())); + if (StringUtils.isNotBlank(userRole) && isAdmin) { // only admin can update UserRole + coselmarUser.setRole(CoselmarUserRole.valueOf(userRole.toUpperCase())); } String organization = user.getOrganization(); @@ -187,6 +193,11 @@ public class UsersWebService extends CoselmarWebServiceSupport { coselmarUser.setOrganization(organization); } + String qualification = user.getQualification(); + if (StringUtils.isNotBlank(qualification)) { + coselmarUser.setQualification(qualification); + } + String newPassword = user.getNewPassword(); if (StringUtils.isNotBlank(newPassword)) { String salt = getServicesContext().generateSalt(); @@ -213,12 +224,7 @@ public class UsersWebService extends CoselmarWebServiceSupport { CoselmarUser user = getCoselmarUserDao().forMailEquals(getCleanMail(mail)).findAny(); String salt = user.getSalt(); - String encodedPassword = getServicesContext().encodePassword(salt, password); - - String userPassword = user.getPassword(); - if (!encodedPassword.equals(userPassword)){ - throw new InvalidCredentialException("Invalid password given"); - } + checkPassword(user.getPassword(), salt, password); // return a Json Web Token for authentication JWTSigner jwtSigner = new JWTSigner(getCoselmarServicesConfig().getWebSecurityKey()); @@ -286,6 +292,23 @@ public class UsersWebService extends CoselmarWebServiceSupport { } } + /** + * Check that the password is the same : encode the one given with the salt, + * and compare with the user password from database + * + * @param currentPassword : password from database + * @param salt : salt use to encode database password + * @param password : given password we want to check + * @throws InvalidCredentialException if the given password is not the same as one from database + */ + protected void checkPassword(String currentPassword, String salt, String password) throws InvalidCredentialException { + String encodedPassword = getServicesContext().encodePassword(salt, password); + + if (!encodedPassword.equals(currentPassword)){ + throw new InvalidCredentialException("Invalid password given"); + } + } + ///////////////////////////////////////////// /////////////// MAIL PART /////////////// ///////////////////////////////////////////// diff --git a/coselmar-rest/src/main/resources/mapping b/coselmar-rest/src/main/resources/mapping index 89a999e..27b2522 100644 --- a/coselmar-rest/src/main/resources/mapping +++ b/coselmar-rest/src/main/resources/mapping @@ -38,8 +38,8 @@ DELETE /v1/documents/{documentId} DocumentsWebService.deleteDocume GET /v1/users UsersWebService.getUsers GET /v1/users/{userId} UsersWebService.getUser -PUT /v1/users/{userId} UsersWebService.modifyUser +POST /v1/users/login UsersWebService.login +POST /v1/users/{userId} UsersWebService.modifyUser POST /v1/users UsersWebService.addUser DELETE /v1/users/{userId} UsersWebService.deleteUser -POST /v1/users/login UsersWebService.login diff --git a/coselmar-ui/src/main/webapp/index.html b/coselmar-ui/src/main/webapp/index.html index d9febf5..968466f 100644 --- a/coselmar-ui/src/main/webapp/index.html +++ b/coselmar-ui/src/main/webapp/index.html @@ -95,7 +95,7 @@ </div> <form class="navbar-form navbar-right" role="form" ng-if="currentUser"> - <div class="form-group">{{currentUser.firstName}} {{currentUser.lastName}}</div> + <div class="form-group">{{currentUser.firstName}} {{currentUser.lastName}} <a href="#/users/{{currentUser.userId}}?edit" class="glyphicon glyphicon-pencil"></a></div> <button type="submit" class="btn btn-danger" ng-click="logout()">Logout</button> </form> </nav> diff --git a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js index 0665085..e31d174 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js @@ -185,10 +185,10 @@ coselmarControllers.controller("NewUserCtrl", ['$scope', '$route', '$location', $scope.user = {'role' : 'expert'}; - $scope.createNewUser = function(){ + $scope.saveUser = function(){ // Call service to create a new user - userService.createUser($scope.user, function() { + userService.saveUser($scope.user, function() { $location.path("/users"); },function(error) { //TODO ymartel 20141118 : deal with error.status or statusText @@ -205,6 +205,11 @@ coselmarControllers.controller("NewUserCtrl", ['$scope', '$route', '$location', coselmarControllers.controller("UserViewCtrl", ['$scope', '$route', '$location', 'userService', '$routeParams', function($scope, $route, $location, userService, $routeParams) { + $scope.editMode = $routeParams.edit; + if ($scope.editMode) { + $scope.editPassword = true; + } + userService.getUser($routeParams.userId, $scope); $scope.deleteUser = function(userId){ @@ -215,4 +220,25 @@ coselmarControllers.controller("UserViewCtrl", }); }; + + $scope.modifyUser = function(){ + $location.search("edit"); + }; + + $scope.saveUser = function(){ + + // Call service to create a new user + userService.saveUser($scope.user, + function() { + // On success, reload the view page + $location.search(""); + + },function(error) { + //TODO ymartel 20141118 : deal with error.status or statusText + console.log("error occurs"); + console.log(error.s); + }); + + }; + } ]); \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/js/coselmar-user-services.js b/coselmar-ui/src/main/webapp/js/coselmar-user-services.js index 617ffcd..f3b24d3 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-user-services.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-user-services.js @@ -32,13 +32,17 @@ function User(resource, config){ var baseURL = config.BASE_URL + "/users"; - this.createUser = function(user, successFunction, failFunction){ + this.saveUser = function(user, successFunction, failFunction){ var formData = new FormData(); formData.append("user", JSON.stringify(user)); // Save the User - var userResource = resource(baseURL, null, { + var serviceURl = baseURL; + if (user.id) { + serviceURl = baseURL + "/" + user.id + } + var userResource = resource(serviceURl, null, { 'save': { method:'POST', transformRequest: angular.identity, @@ -96,4 +100,22 @@ function User(resource, config){ }}); userResource.post(credentials, successFunction, failFunction); } + +// this.saveUser = function(user, successFunction, failFunction){ +// +// var formData = new FormData(); +// formData.append("user", JSON.stringify(user)); +// +// // Save the User +// var userResource = resource(baseURL + "/" + user.id, null, { +// 'save': { +// method: 'POST', +// transformRequest: angular.identity, +// headers:{ +// 'Content-Type': undefined +// } +// } +// }); +// userResource.save(null, formData, successFunction, failFunction); +// } }; \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/views/users/edituser.html b/coselmar-ui/src/main/webapp/views/users/edituser.html new file mode 100644 index 0000000..35f1e52 --- /dev/null +++ b/coselmar-ui/src/main/webapp/views/users/edituser.html @@ -0,0 +1,94 @@ + <div class=""> + + <form name="userForm" class="form-horizontal" role="form" ng-submit="saveUser()"> + + <div class="form-group"> + <label class="col-md-4 control-label">FirstName</label> + + <div class="col-md-5"> + <input type="text" class="form-control" name="firstName" + ng-model="user.firstName" required/> + </div> + </div> + + <div class="form-group"> + <label class="col-md-4 control-label">Name</label> + + <div class="col-md-5"> + <input type="text" class="form-control" name="name" + ng-model="user.name" required/> + </div> + </div> + + <div class="form-group" ng-if="currentUser.role == 'ADMIN'"> + <label class="col-md-4 control-label">Role</label> + + <div class="col-md-5"> + <select class="form-control" name="role" ng-model="user.role"> + <option value="ADMIN">Admin</option> + <option value="SUPERVISOR">Supervisor</option> + <option value="EXPERT">Expert</option> + <option value="MEMBER">Member</option> + <option value="CLIENT">Client</option> + </select> + </div> + + </div> + + <div class="form-group"> + <label class="col-md-4 control-label">Mail</label> + + <div class="col-md-5"> + <input type="email" class="form-control" name="mail" + ng-model="user.mail" required/> + </div> + + </div> + + <div class="form-group"> + <label class="col-md-4 control-label">Organization</label> + + <div class="col-md-5"> + <input type="text" class="form-control" name="organization" + ng-model="user.organization" /> + </div> + + </div> + + <div class="form-group"> + <label class="col-md-4 control-label">Qualification</label> + + <div class="col-md-5"> + <input type="text" class="form-control" name="qualification" + ng-model="user.qualification" required/> + </div> + + </div> + + <div class="form-group" ng-if="currentUser && currentUser.userId == user.id"> + <label class="col-md-4 control-label">Tape your current password to validate</label> + + <div class="col-md-5"> + <input type="password" class="form-control" name="password" + ng-model="user.password" required/> + </div> + + </div> + + <div class="form-group" ng-if="editPassword"> + <label class="col-md-4 control-label">New Password</label> + + <div class="col-md-5"> + <input type="password" class="form-control" name="newPassword" + ng-model="user.newPassword" ng-minlength="6" placeholder="change password"/> + </div> + + </div> + + <div class="form-group" ng-if="userForm.$valid || currentUser.role == 'ADMIN'"> + <div style="padding-left: 200px"> + <input type="submit" value="Validate" class="btn btn-primary"/> + </div> + </div> + </form> + </div> diff --git a/coselmar-ui/src/main/webapp/views/users/newuser.html b/coselmar-ui/src/main/webapp/views/users/newuser.html index 3fa8e87..40d6b50 100644 --- a/coselmar-ui/src/main/webapp/views/users/newuser.html +++ b/coselmar-ui/src/main/webapp/views/users/newuser.html @@ -12,67 +12,8 @@ <li>Client</li> </ul> </div> - <div style="padding-bottom: 50px"> + <div style="padding-bottom: 50px" ng-include="src='views/users/edituser.html'"> - <div class=""> - - <form class="form-horizontal" role="form" ng-submit="createNewUser()"> - - <div class="form-group"> - <label class="col-md-4 control-label">FirstName</label> - - <div class="col-md-5"> - <input type="text" class="form-control" name="firstName" ng-model="user.firstName" required/> - </div> - </div> - - <div class="form-group"> - <label class="col-md-4 control-label">Name</label> - - <div class="col-md-5"> - <input type="text" class="form-control" name="name" ng-model="user.name" required/> - </div> - </div> - - <div class="form-group"> - <label class="col-md-4 control-label">Role</label> - - <div class="col-md-5"> - <select class="form-control" name="role" ng-model="user.role"> - <option value="supervisor">Supervisor</option> - <option value="expert">Expert</option> - <option value="member">Member</option> - <option value="client">Client</option> - </select> - </div> - - </div> - - <div class="form-group"> - <label class="col-md-4 control-label">Mail</label> - - <div class="col-md-5"> - <input type="text" class="form-control" name="mail" ng-model="user.mail" required/> - </div> - - </div> - - <div class="form-group"> - <label class="col-md-4 control-label">Qualification</label> - - <div class="col-md-5"> - <input type="text" class="form-control" name="qualification" ng-model="user.qualification" required/> - </div> - - </div> - - <div class="form-group"> - <div style="padding-left: 200px"> - <input type="submit" value="Submit" class="btn btn-primary" /> - </div> - </div> - </form> - </div> </div> diff --git a/coselmar-ui/src/main/webapp/views/users/user.html b/coselmar-ui/src/main/webapp/views/users/user.html index 3245cba..37514ad 100644 --- a/coselmar-ui/src/main/webapp/views/users/user.html +++ b/coselmar-ui/src/main/webapp/views/users/user.html @@ -4,7 +4,7 @@ {{user.firstName}} {{user.name}} </h1> </div> - <div> + <div ng-if="!editMode" > <table class="table table-striped"> <tr> <td>Contact</td> @@ -15,12 +15,22 @@ <td>{{user.qualification}}</td> </tr> <tr> + <td>Organization</td> + <td>{{user.organization}}</td> + </tr> + <tr> <td>Role</td> <td>{{user.role}}</td> </tr> </table> <div style="padding-left: 200px"> - <a class="btn btn-danger" ng-click="deleteUser(user.id)">Delete</a> + <a class="btn btn-warning" ng-click="modifyUser()">Modify</a> + <a class="btn btn-danger" ng-click="deleteUser(user.id)" ng-if="currentUser.role == 'ADMIN'">Delete</a> </div> </div> + + <div ng-if="editMode" style="padding: 30px 0px 50px 0px"> + <div ng-include="src='views/users/edituser.html'" ></div> + </div> + </div> \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/views/users/users.html b/coselmar-ui/src/main/webapp/views/users/users.html index 0f15a7d..c9db771 100644 --- a/coselmar-ui/src/main/webapp/views/users/users.html +++ b/coselmar-ui/src/main/webapp/views/users/users.html @@ -26,6 +26,7 @@ <th>Name</th> <th>Mail</th> <th>Qualification</th> + <th>Organization</th> <th>Role</th> <th></th> </tr> @@ -33,8 +34,9 @@ <td><a href="#/users/{{user.id}}">{{user.firstname}} {{user.name}}</a></td> <td>{{user.mail}}</td> <td>{{user.qualification}}</td> + <td>{{user.organization}}</td> <td>{{user.role}}</td> - <td><a class="btn btn-danger" ng-click="deleteUser(user.id)">Delete</a></td> + <td><a class="btn btn-warning" href="users/{{user.id}}?edit">Modify</a><a class="btn btn-danger" ng-click="deleteUser(user.id)">Delete</a></td> </tr> </table> </div> -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.