branch develop updated (62e996a -> 984fbd9)
This is an automated email from the git hooks/post-receive script. New change to branch develop in repository coselmar. See http://git.codelutin.com/coselmar.git from 62e996a [jgitflow-maven-plugin]Updating develop poms back to pre merge state new 7c08712 prepare User Service new bf4d364 prepare user ui adds 3b099c5 prepare User Service new c11b794 Merge branch 'feature/6012-create-user' of https://git.codelutin.com/coselmar into feature/6012-create-user new 8575bb0 prepare users javascript services new 077f21d prepare user account creation and login operrations new 0eaf8f5 prepare user account creation and login operrations new bc986fa prepare mail support new 310cf01 add organization in user new a6e1f56 finish user creation, add login method new 2e46837 Merge branch 'feature/6012-create-user' into develop new 984fbd9 Merge branch 'develop' of https://git.codelutin.com/coselmar into develop The 11 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit 984fbd9d0062e2a83dfea0a7ed23a3d841ed55de Merge: 2e46837 62e996a Author: Yannick Martel <martel@©odelutin.com> Date: Fri Nov 21 11:32:43 2014 +0100 Merge branch 'develop' of https://git.codelutin.com/coselmar into develop commit 2e468378c44cc40fc6a92e80410ea1d79967f193 Merge: 9f52978 a6e1f56 Author: Yannick Martel <martel@©odelutin.com> Date: Fri Nov 21 11:31:49 2014 +0100 Merge branch 'feature/6012-create-user' into develop commit a6e1f56d663bf878bd9fb49f7995227233f1ff6d Author: Yannick Martel <martel@©odelutin.com> Date: Fri Nov 21 11:13:21 2014 +0100 finish user creation, add login method commit 310cf01e356ed292016809cbc0c7e388266f06a7 Author: Yannick Martel <martel@©odelutin.com> Date: Thu Nov 20 14:49:26 2014 +0100 add organization in user commit bc986faef0b94cd4c224056157bdc160875f1f19 Author: Yannick Martel <martel@©odelutin.com> Date: Wed Nov 19 11:21:40 2014 +0100 prepare mail support commit 0eaf8f5e894f766dc6e4cafd35efe526321ad447 Author: Yannick Martel <martel@©odelutin.com> Date: Tue Nov 18 18:13:26 2014 +0100 prepare user account creation and login operrations commit 077f21d986c2ad2fac97f141d797a231e660db39 Author: Yannick Martel <martel@©odelutin.com> Date: Tue Nov 18 18:12:59 2014 +0100 prepare user account creation and login operrations commit 8575bb0b19cb411f8776f117bd57184a99dc2c64 Author: Yannick Martel <martel@©odelutin.com> Date: Mon Nov 17 20:20:02 2014 +0100 prepare users javascript services commit c11b794476da8699ab425796e7143e7d34ebeb62 Merge: bf4d364 3b099c5 Author: Yannick Martel <martel@©odelutin.com> Date: Mon Nov 17 18:28:38 2014 +0100 Merge branch 'feature/6012-create-user' of https://git.codelutin.com/coselmar into feature/6012-create-user commit bf4d364dd5d24e3beb4292101a02af059e9d5b47 Author: Yannick Martel <martel@©odelutin.com> Date: Fri Nov 14 18:31:18 2014 +0100 prepare user ui commit 7c08712382b5cd402602f37cf425e27191f533b9 Author: Yannick Martel <martel@©odelutin.com> Date: Mon Nov 10 17:50:19 2014 +0100 prepare User Service Summary of changes: .gitignore | 3 +- .../src/main/xmi/coselmar-model.zargo | Bin 5234 -> 6024 bytes coselmar-rest/pom.xml | 59 ++++++ .../coselmar/beans/UserAccountCreatedMail.java | 81 +++++++ .../java/fr/ifremer/coselmar/beans/UserBean.java | 92 ++++++++ .../coselmar/converter/BeanEntityConverter.java | 13 ++ .../services/CoselmarRestApplicationListener.java | 4 +- .../coselmar/services/CoselmarServicesContext.java | 11 +- .../services/CoselmarWebServiceSupport.java | 1 + .../services/DefaultCoselmarServicesContext.java | 67 ++++++ .../services/config/CoselmarServicesConfig.java | 48 ++++- .../config/CoselmarServicesConfigOption.java | 41 +++- .../errors/InvalidCredentialException.java | 11 + .../coselmar/services/v1/UsersWebService.java | 232 +++++++++++++++++++++ .../resources/mail/UserAccountCreatedMail.mustache | 8 + .../mail/UserAccountCreatedMail_fr.mustache | 8 + coselmar-rest/src/main/resources/mapping | 11 +- .../services/AbstractCoselmarWebServiceTest.java | 92 ++++++++ .../services/FakeCoselmarApplicationContext.java | 224 ++++++++++++++++++++ .../services/FakeCoselmarServicesContext.java | 51 +++++ .../coselmar/services/UsersWebServiceTest.java | 59 ++++++ .../resources/coselmar-test.properties} | 2 + coselmar-ui/src/main/webapp/index.html | 1 + .../src/main/webapp/js/coselmar-controllers.js | 72 ++++++- .../src/main/webapp/js/coselmar-services.js | 20 +- .../src/main/webapp/js/coselmar-user-services.js | 82 ++++++++ coselmar-ui/src/main/webapp/js/coselmar.js | 23 +- .../webapp/views/{ => documents}/document.html | 0 .../webapp/views/{ => documents}/documents.html | 0 .../webapp/views/{ => documents}/newdocument.html | 0 .../src/main/webapp/views/users/newuser.html | 79 +++++++ coselmar-ui/src/main/webapp/views/users/user.html | 26 +++ coselmar-ui/src/main/webapp/views/users/users.html | 41 ++++ pom.xml | 56 +++++ 34 files changed, 1476 insertions(+), 42 deletions(-) create mode 100644 coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserAccountCreatedMail.java create mode 100644 coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java create mode 100644 coselmar-rest/src/main/java/fr/ifremer/coselmar/services/errors/InvalidCredentialException.java create mode 100644 coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UsersWebService.java create mode 100644 coselmar-rest/src/main/resources/mail/UserAccountCreatedMail.mustache create mode 100644 coselmar-rest/src/main/resources/mail/UserAccountCreatedMail_fr.mustache create mode 100644 coselmar-rest/src/test/java/fr/ifremer/coselmar/services/AbstractCoselmarWebServiceTest.java create mode 100644 coselmar-rest/src/test/java/fr/ifremer/coselmar/services/FakeCoselmarApplicationContext.java create mode 100644 coselmar-rest/src/test/java/fr/ifremer/coselmar/services/FakeCoselmarServicesContext.java create mode 100644 coselmar-rest/src/test/java/fr/ifremer/coselmar/services/UsersWebServiceTest.java copy coselmar-rest/src/{main/resources/coselmar-services.properties => test/resources/coselmar-test.properties} (97%) create mode 100644 coselmar-ui/src/main/webapp/js/coselmar-user-services.js rename coselmar-ui/src/main/webapp/views/{ => documents}/document.html (100%) rename coselmar-ui/src/main/webapp/views/{ => documents}/documents.html (100%) rename coselmar-ui/src/main/webapp/views/{ => documents}/newdocument.html (100%) create mode 100644 coselmar-ui/src/main/webapp/views/users/newuser.html create mode 100644 coselmar-ui/src/main/webapp/views/users/user.html create mode 100644 coselmar-ui/src/main/webapp/views/users/users.html -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
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 7c08712382b5cd402602f37cf425e27191f533b9 Author: Yannick Martel <martel@©odelutin.com> Date: Mon Nov 10 17:50:19 2014 +0100 prepare User Service --- .../src/main/xmi/coselmar-model.zargo | Bin 5234 -> 5991 bytes .../java/fr/ifremer/coselmar/beans/UserBean.java | 73 ++++++++++++++++++ .../coselmar/converter/BeanEntityConverter.java | 12 +++ .../coselmar/services/v1/UserWebService.java | 85 +++++++++++++++++++++ 4 files changed, 170 insertions(+) diff --git a/coselmar-persistence/src/main/xmi/coselmar-model.zargo b/coselmar-persistence/src/main/xmi/coselmar-model.zargo index 82b4570..0ddcf03 100644 Binary files a/coselmar-persistence/src/main/xmi/coselmar-model.zargo and b/coselmar-persistence/src/main/xmi/coselmar-model.zargo differ diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java new file mode 100644 index 0000000..81246b8 --- /dev/null +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java @@ -0,0 +1,73 @@ +package fr.ifremer.coselmar.beans; + +import java.io.Serializable; + +/** + * @author ymartel <martel@codelutin.com> + */ +public class UserBean implements Serializable { + + protected String id; + protected String firstName; + protected String name; + protected String mail; + protected String role; + protected String qualification; + + public UserBean(String id, String firstName, String name, String mail, String role, String qualification) { + this.id = id; + this.firstName = firstName; + this.name = name; + this.mail = mail; + this.role = role; + this.qualification = qualification; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMail() { + return mail; + } + + public void setMail(String mail) { + this.mail = mail; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String getQualification() { + return qualification; + } + + public void setQualification(String qualification) { + this.qualification = qualification; + } +} diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java index a7cd935..d90136e 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java @@ -27,7 +27,9 @@ package fr.ifremer.coselmar.converter; import java.util.Date; import fr.ifremer.coselmar.beans.DocumentBean; +import fr.ifremer.coselmar.beans.UserBean; import fr.ifremer.coselmar.persistence.entity.Document; +import fr.ifremer.coselmar.persistence.entity.User; /** * @author ymartel <martel@codelutin.com> @@ -46,4 +48,14 @@ public class BeanEntityConverter { document.getMimeType()); } + public static UserBean toBean(User user) { + String userLightId = user.getTopiaId().replace(User.class.getCanonicalName() + "_", ""); + return new UserBean(userLightId, + user.getFirstname(), + user.getName(), + user.getMail(), + user.getRole().name(), + user.getQualification()); + } + } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UserWebService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UserWebService.java new file mode 100644 index 0000000..0005b1f --- /dev/null +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UserWebService.java @@ -0,0 +1,85 @@ +package fr.ifremer.coselmar.services.v1; + +import java.util.ArrayList; +import java.util.List; + +import com.google.common.base.Preconditions; +import fr.ifremer.coselmar.beans.UserBean; +import fr.ifremer.coselmar.converter.BeanEntityConverter; +import fr.ifremer.coselmar.persistence.entity.User; +import fr.ifremer.coselmar.persistence.entity.UserRole; +import fr.ifremer.coselmar.services.CoselmarWebServiceSupport; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; + +import static org.apache.commons.logging.LogFactory.getLog; + +/** + * @author ymartel <martel@codelutin.com> + */ +public class UserWebService extends CoselmarWebServiceSupport { + + private static final Log log = getLog(UserWebService.class); + + public UserBean getUser(String userId) { + + // reconstitute full id + String fullId = User.class.getCanonicalName() + "_" + userId; + + User user = getUserDao().forTopiaIdEquals(fullId).findUnique(); + UserBean userBean = BeanEntityConverter.toBean(user); + return userBean; + } + + public List<UserBean> getUsers(String searchKey) { + + List<User> userList; + if (StringUtils.isNotBlank(searchKey)) { + //TODO find on all parts ? + userList = new ArrayList<>(); + } else { + userList = getUserDao().findAll(); + } + List<UserBean> result = new ArrayList<>(userList.size()); + + for (User user : userList) { + UserBean userBean = BeanEntityConverter.toBean(user); + result.add(userBean); + } + + return result; + } + + public void addUser(UserBean user) { + Preconditions.checkNotNull(user); + + User userEntity = getUserDao().create(); + + userEntity.setFirstname(user.getFirstName()); + userEntity.setName(user.getName()); + userEntity.setMail(user.getMail()); + userEntity.setRole(UserRole.valueOf(user.getRole().toUpperCase())); + userEntity.setQualification(user.getQualification()); + + //generate a password & a salt + + commit(); + + // send mail to user with password + } + + public void changePassword() { + //TODO ymartel + } + + public void deleteUser(String userId) { + + // reconstitute full id + String fullId = User.class.getCanonicalName() + "_" + userId; + + User user = getUserDao().forTopiaIdEquals(fullId).findUnique(); + getUserDao().delete(user); + + commit(); + } +} -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
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 bf4d364dd5d24e3beb4292101a02af059e9d5b47 Author: Yannick Martel <martel@©odelutin.com> Date: Fri Nov 14 18:31:18 2014 +0100 prepare user ui --- .../src/main/webapp/views/users/newuser.html | 79 ++++++++++++++++++++++ coselmar-ui/src/main/webapp/views/users/user.html | 26 +++++++ coselmar-ui/src/main/webapp/views/users/users.html | 41 +++++++++++ 3 files changed, 146 insertions(+) diff --git a/coselmar-ui/src/main/webapp/views/users/newuser.html b/coselmar-ui/src/main/webapp/views/users/newuser.html new file mode 100644 index 0000000..6a75c85 --- /dev/null +++ b/coselmar-ui/src/main/webapp/views/users/newuser.html @@ -0,0 +1,79 @@ +<div style="padding: 0px 0px 0px 30px"> + <div class="page-header" style="margin: 0"> + <h2>Add new user</h2> + </div> + + <div style="padding-top: 15px"> + Create new user, with one of following roles : + <ul> + <li>Supervisor : Kind of big manager, who relays member/client question and assigns expert on questions</li> + <li>Expert : Scientist, who can add new document in the repository and see other scientist documents (according file permission)</li> + <li>Member</li> + <li>Client</li> + </ul> + </div> + <div style="padding-bottom: 50px"> + + <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="file" 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> + +</div> \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/views/users/user.html b/coselmar-ui/src/main/webapp/views/users/user.html new file mode 100644 index 0000000..3245cba --- /dev/null +++ b/coselmar-ui/src/main/webapp/views/users/user.html @@ -0,0 +1,26 @@ +<div style="padding: 0px 0px 0px 30px"> + <div class="page-header" style="margin: 0"> + <h1> + {{user.firstName}} {{user.name}} + </h1> + </div> + <div> + <table class="table table-striped"> + <tr> + <td>Contact</td> + <td>{{user.mail}}</td> + </tr> + <tr> + <td>Qualification</td> + <td>{{user.qualification}}</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> + </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 new file mode 100644 index 0000000..8f2c904 --- /dev/null +++ b/coselmar-ui/src/main/webapp/views/users/users.html @@ -0,0 +1,41 @@ +<div style="padding: 0px 0px 0px 30px"> + <div class="page-header" style="margin: 0"> + <h1> + <!-- Heading goes here --> + All Users + </h1> + </div> + + <div> + <div> + <div class="form-group"> + <a href="#/users/new" class="form-inline navbar-left btn btn-primary">Add an user</a> + </div> + <form class="form-inline pull-right" role="userOptions" ng-submit="searchUser()"> + <div class="form-group"> + <input type="search" class="form-control" placeholder="Search an user" ng-model="searchKeywords" ng-list /> + </div> + <div class="form-group"> + <button type="submit" class="btn btn-default glyphicon glyphicon-search"></button> + </div> + </form> + </div> + <br/> + <table class="table"> + <tr> + <th>Name</th> + <th>Mail</th> + <th>Qualification</th> + <th>Role</th> + <th></th> + </tr> + <tr ng-repeat="user in users"> + <td><a href="#/user/{{user.id}}">{{user.firstname}} {{user.name}}</a></td> + <td>{{user.mail}}</td> + <td>{{user.qualification}}</td> + <td>{{user.role}}</td> + <td><a class="btn btn-danger" ng-click="deleteUser(user.id)">Delete</a></td> + </tr> + </table> + </div> +</div> \ No newline at end of file -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
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 c11b794476da8699ab425796e7143e7d34ebeb62 Merge: bf4d364 3b099c5 Author: Yannick Martel <martel@©odelutin.com> Date: Mon Nov 17 18:28:38 2014 +0100 Merge branch 'feature/6012-create-user' of https://git.codelutin.com/coselmar into feature/6012-create-user -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
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 8575bb0b19cb411f8776f117bd57184a99dc2c64 Author: Yannick Martel <martel@©odelutin.com> Date: Mon Nov 17 20:20:02 2014 +0100 prepare users javascript services --- coselmar-bundle/pom.xml | 2 +- coselmar-persistence/pom.xml | 2 +- coselmar-rest/pom.xml | 2 +- .../{UserWebService.java => UsersWebService.java} | 4 +- coselmar-rest/src/main/resources/mapping | 7 ++ coselmar-ui/pom.xml | 2 +- coselmar-ui/src/main/webapp/index.html | 1 + .../src/main/webapp/js/coselmar-controllers.js | 67 +++++++++++++++++- .../src/main/webapp/js/coselmar-services.js | 20 +++--- .../src/main/webapp/js/coselmar-user-services.js | 82 ++++++++++++++++++++++ coselmar-ui/src/main/webapp/js/coselmar.js | 23 ++++-- .../webapp/views/{ => documents}/document.html | 0 .../webapp/views/{ => documents}/documents.html | 0 .../webapp/views/{ => documents}/newdocument.html | 0 .../src/main/webapp/views/users/newuser.html | 2 +- pom.xml | 4 +- 16 files changed, 194 insertions(+), 24 deletions(-) diff --git a/coselmar-bundle/pom.xml b/coselmar-bundle/pom.xml index 7955ac8..70fdc2b 100644 --- a/coselmar-bundle/pom.xml +++ b/coselmar-bundle/pom.xml @@ -27,7 +27,7 @@ <parent> <groupId>fr.ifremer</groupId> <artifactId>coselmar</artifactId> - <version>0.1</version> + <version>0.2-SNAPSHOT</version> </parent> <groupId>fr.ifremer.coselmar</groupId> diff --git a/coselmar-persistence/pom.xml b/coselmar-persistence/pom.xml index fd8a8aa..21faa60 100644 --- a/coselmar-persistence/pom.xml +++ b/coselmar-persistence/pom.xml @@ -27,7 +27,7 @@ <parent> <groupId>fr.ifremer</groupId> <artifactId>coselmar</artifactId> - <version>0.1</version> + <version>0.2-SNAPSHOT</version> </parent> <groupId>fr.ifremer.coselmar</groupId> diff --git a/coselmar-rest/pom.xml b/coselmar-rest/pom.xml index 402db18..b58962c 100644 --- a/coselmar-rest/pom.xml +++ b/coselmar-rest/pom.xml @@ -27,7 +27,7 @@ <parent> <groupId>fr.ifremer</groupId> <artifactId>coselmar</artifactId> - <version>0.1</version> + <version>0.2-SNAPSHOT</version> </parent> <groupId>fr.ifremer.coselmar</groupId> diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UserWebService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UsersWebService.java similarity index 94% rename from coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UserWebService.java rename to coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UsersWebService.java index 0005b1f..3add9f3 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UserWebService.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UsersWebService.java @@ -17,9 +17,9 @@ import static org.apache.commons.logging.LogFactory.getLog; /** * @author ymartel <martel@codelutin.com> */ -public class UserWebService extends CoselmarWebServiceSupport { +public class UsersWebService extends CoselmarWebServiceSupport { - private static final Log log = getLog(UserWebService.class); + private static final Log log = getLog(UsersWebService.class); public UserBean getUser(String userId) { diff --git a/coselmar-rest/src/main/resources/mapping b/coselmar-rest/src/main/resources/mapping index 603b956..d18f439 100644 --- a/coselmar-rest/src/main/resources/mapping +++ b/coselmar-rest/src/main/resources/mapping @@ -33,3 +33,10 @@ POST /v1/documents DocumentsWebService.addDocument PUT /v1/documents/{documentId} DocumentsWebService.saveDocument DELETE /v1/documents/{documentId} DocumentsWebService.deleteDocument +# Users Api + +GET /v1/users UsersWebService.getUsers +GET /v1/users/{userId} UsersWebService.getUser +POST /v1/users UsersWebService.addUser +DELETE /v1/users/{userId} UsersWebService.deleteUser + diff --git a/coselmar-ui/pom.xml b/coselmar-ui/pom.xml index 1c4f01f..f6a7134 100644 --- a/coselmar-ui/pom.xml +++ b/coselmar-ui/pom.xml @@ -27,7 +27,7 @@ <parent> <groupId>fr.ifremer</groupId> <artifactId>coselmar</artifactId> - <version>0.1</version> + <version>0.2-SNAPSHOT</version> </parent> <groupId>fr.ifremer.coselmar</groupId> diff --git a/coselmar-ui/src/main/webapp/index.html b/coselmar-ui/src/main/webapp/index.html index e0c9e5c..f7f222d 100644 --- a/coselmar-ui/src/main/webapp/index.html +++ b/coselmar-ui/src/main/webapp/index.html @@ -34,6 +34,7 @@ <script src="nuiton-js/bootstrap.js"></script> <script src="js/coselmar-controllers.js"></script> <script src="js/coselmar-services.js"></script> + <script src="js/coselmar-user-services.js"></script> <script src="js/coselmar.js"></script> </head> diff --git a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js index 02a3206..5e5a756 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js @@ -107,4 +107,69 @@ coselmarControllers.directive('ngFileModel', ['$parse', function ($parse) { }); } }; -}]); \ No newline at end of file +}]); + + +///////////////////////////////////////////////// +////////////// Users Part ///////////////////// +///////////////////////////////////////////////// + +// Controller for All User View +coselmarControllers.controller("UsersCtrl", ['$scope', '$route', '$routeParams', '$location', 'userService', function($scope, $route, $routeParams, $location, userService){ + + //manage keywords if given + $scope.searchKeywords = []; + var keywords = $routeParams.keywords; + if (Array.isArray(keywords)) { + $scope.searchKeywords = keywords; + } else if (keywords) { + $scope.searchKeywords.push(keywords); + } + + userService.getUsers($scope); + + $scope.deleteUser = function(userId){ + + userService.deleteUser(userId, $scope, function() { + // Go back to documents list + $route.reload(); + }); + }; + + $scope.searchUsers = function(){ + $location.search('keywords', $scope.searchKeywords); + } +}]); + + +// Controller for new user View +coselmarControllers.controller("NewUserCtrl", ['$scope', '$route', 'userService', function($scope, $route, userService){ + + $scope.createNewUser = function(){ +// var user = {'privacy':$scope.privacy, 'role':'expert'}; + + // Call service to create a new user + userService.createUser($scope.user, $scope, function() { + $location.path("/users"); + }); + + // Reload the page + $route.reload(); + }; +}]); + +// Controller for single document View +coselmarControllers.controller("UserViewCtrl", + ['$scope', '$route', '$location', 'userService', '$routeParams', function($scope, $route, $location, userService, $routeParams) { + + userService.getUser($routeParams.userId, $scope); + + $scope.deleteUser = function(userId){ + + documentService.deleteUser(documentId, $scope, function() { + // Go back to users list + $location.path("/users"); + }); + + }; +} ]); \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/js/coselmar-services.js b/coselmar-ui/src/main/webapp/js/coselmar-services.js index e4c462b..ce2b0da 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-services.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-services.js @@ -37,8 +37,8 @@ function Document(resource){ formData.append("uploadFile", file); formData.append("document", JSON.stringify(metadata)); // Save the document -// var docResource = resource('http://localhost:8081/services/v1/documents', null, { - var docResource = resource('v1/documents', null, { + var docResource = resource('http://localhost:8081/services/v1/documents', null, { +// var docResource = resource('v1/documents', null, { 'upload': { method:'POST', transformRequest: angular.identity, @@ -54,8 +54,8 @@ function Document(resource){ this.getDocument = function(id, scope){ // Load the document -// var docResource = resource('http://localhost:8081/services/v1/documents/:documentId', {documentId:'@documentId'}); - var docResource = resource('v1/documents/:documentId', {documentId:'@documentId'}); + var docResource = resource('http://localhost:8081/services/v1/documents/:documentId', {documentId:'@documentId'}); +// var docResource = resource('v1/documents/:documentId', {documentId:'@documentId'}); docResource.get({documentId:id}, function(document){ console.log(document); scope.document = document; @@ -65,15 +65,15 @@ function Document(resource){ this.deleteDocument = function(id, scope, successFunction){ // Load the document -// var docResource = resource('http://localhost:8081/services/v1/documents/:documentId', {documentId:'@id'}); - var docResource = resource('v1/documents/:documentId', {documentId:'@documentId'}); + var docResource = resource('http://localhost:8081/services/v1/documents/:documentId', {documentId:'@id'}); +// var docResource = resource('v1/documents/:documentId', {documentId:'@documentId'}); docResource.delete({documentId:id}, successFunction); } this.getDocumentFile = function(id, scope){ // Load the document - var docResource = resource('http://localhost:8081/services/v1/documents/:documentId/file', {documentId:'@documentId'}); -// var docResource = resource('v1/documents/:documentId/file', {documentId:'@documentId'}); +// var docResource = resource('http://localhost:8081/services/v1/documents/:documentId/file', {documentId:'@documentId'}); + var docResource = resource('v1/documents/:documentId/file', {documentId:'@documentId'}); docResource.get({documentId:id}, function(file){ // redirect to document page ? }); @@ -83,8 +83,8 @@ function Document(resource){ // Load all documents console.log("loading all documents"); -// var docResource = resource('http://localhost:8081/services/v1/documents', {searchKeywords : scope.searchKeywords}); - var docResource = resource('v1/documents', {searchKeywords : scope.searchKeywords}); + var docResource = resource('http://localhost:8081/services/v1/documents', {searchKeywords : scope.searchKeywords}); +// var docResource = resource('v1/documents', {searchKeywords : scope.searchKeywords}); docResource.query(function(documents){ scope.documents = documents; }, function(errorResult) { diff --git a/coselmar-ui/src/main/webapp/js/coselmar-user-services.js b/coselmar-ui/src/main/webapp/js/coselmar-user-services.js new file mode 100644 index 0000000..5ff11d0 --- /dev/null +++ b/coselmar-ui/src/main/webapp/js/coselmar-user-services.js @@ -0,0 +1,82 @@ +/* + * #%L + * Coselmar :: UI + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2014 Ifremer, Code Lutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +coselmarServices.factory('userService', ['$resource', function($resource){ + return new User($resource); +}]); + +function User(resource){ + + var baseURL = "http://localhost:8081/services/v1/users"; + + this.resource = resource; +// this.baseURL = "v1/users"; + + this.createUser = function(user, scope, successFunction){ + +// var formData = new FormData(); +// formData.append("user", JSON.stringify(user)); + // Save the User + var userResource = resource(baseURL, {user:user}); +// var userResource = resource(baseURL, null, { +// 'save': { +// method:'POST', +// transformRequest: angular.identity, +// headers:{ +// 'Content-Type':undefined +// } +// } +// }); + userResource.save({user:user}, successFunction); + } + + this.getUser = function(id, scope){ + // Load the User + var userResource = resource(baseURL + '/:userId', {userId:'@userId'}); + userResource.get({userId:id}, function(user){ + scope.user = user; + }); + } + + this.deleteUser = function(id, scope, successFunction){ + + var userResource = resource(baseURL + '/:userId', {userId:'@id'}); + userResource.delete({userId:id}, successFunction); + } + + this.getUsers = function(scope){ + // Load all users + + var userResource = resource(baseURL, {searchKeywords : scope.searchKeywords}); + userResource.query(function(users){ + scope.users = users; + }, function(errorResult) { + // let's log errors + if(errorResult.status === 404) { + console.log("Service unreachable, deal it boy!"); + } else { + console.log("WTF ?!?"); + } + }); + } +}; \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/js/coselmar.js b/coselmar-ui/src/main/webapp/js/coselmar.js index 70d0ad2..1a342e2 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar.js +++ b/coselmar-ui/src/main/webapp/js/coselmar.js @@ -24,17 +24,32 @@ var coselmarApp = angular.module("coselmarApp", ['ngRoute', 'ngResource', 'coselmarControllers', 'coselmarServices']); coselmarApp.config(['$routeProvider', function($routeProvider) { - $routeProvider.when('/documents', { + $routeProvider + //documents + .when('/documents', { controller : 'DocumentsCtrl', - templateUrl : 'views/documents.html' + templateUrl : 'views/documents/documents.html' }).when('/documents/new', { controller : 'NewDocumentCtrl', - templateUrl : 'views/newdocument.html' + templateUrl : 'views/documents/newdocument.html' }).when('/documents/:documentId', { controller : 'DocumentViewCtrl', - templateUrl : 'views/document.html' + templateUrl : 'views/documents/document.html' + + //users + }).when('/users', { + controller : 'UsersCtrl', + templateUrl : 'views/users/users.html' + + }).when('/users/new', { + controller : 'NewUserCtrl', + templateUrl : 'views/users/newuser.html' + + }).when('/users/:userId', { + controller : 'UserViewCtrl', + templateUrl : 'views/users/users.html' }).otherwise({ redirectTo: '/', diff --git a/coselmar-ui/src/main/webapp/views/document.html b/coselmar-ui/src/main/webapp/views/documents/document.html similarity index 100% rename from coselmar-ui/src/main/webapp/views/document.html rename to coselmar-ui/src/main/webapp/views/documents/document.html diff --git a/coselmar-ui/src/main/webapp/views/documents.html b/coselmar-ui/src/main/webapp/views/documents/documents.html similarity index 100% rename from coselmar-ui/src/main/webapp/views/documents.html rename to coselmar-ui/src/main/webapp/views/documents/documents.html diff --git a/coselmar-ui/src/main/webapp/views/newdocument.html b/coselmar-ui/src/main/webapp/views/documents/newdocument.html similarity index 100% rename from coselmar-ui/src/main/webapp/views/newdocument.html rename to coselmar-ui/src/main/webapp/views/documents/newdocument.html diff --git a/coselmar-ui/src/main/webapp/views/users/newuser.html b/coselmar-ui/src/main/webapp/views/users/newuser.html index 6a75c85..3fa8e87 100644 --- a/coselmar-ui/src/main/webapp/views/users/newuser.html +++ b/coselmar-ui/src/main/webapp/views/users/newuser.html @@ -22,7 +22,7 @@ <label class="col-md-4 control-label">FirstName</label> <div class="col-md-5"> - <input type="file" class="form-control" name="firstName" ng-model="user.firstName" required/> + <input type="text" class="form-control" name="firstName" ng-model="user.firstName" required/> </div> </div> diff --git a/pom.xml b/pom.xml index d74e758..a11ecaa 100644 --- a/pom.xml +++ b/pom.xml @@ -27,12 +27,12 @@ <parent> <groupId>org.nuiton</groupId> <artifactId>codelutinpom</artifactId> - <version>1.5</version> + <version>1.6</version> </parent> <groupId>fr.ifremer</groupId> <artifactId>coselmar</artifactId> - <version>0.1</version> + <version>0.2-SNAPSHOT</version> <packaging>pom</packaging> <name>Coselmar</name> -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
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 077f21d986c2ad2fac97f141d797a231e660db39 Author: Yannick Martel <martel@©odelutin.com> Date: Tue Nov 18 18:12:59 2014 +0100 prepare user account creation and login operrations --- coselmar-rest/pom.xml | 46 +++++++++++++++ .../java/fr/ifremer/coselmar/beans/UserBean.java | 9 +++ .../services/CoselmarRestApplicationListener.java | 4 +- .../coselmar/services/CoselmarServicesContext.java | 11 ++-- .../services/CoselmarWebServiceSupport.java | 1 + .../services/DefaultCoselmarServicesContext.java | 67 ++++++++++++++++++++++ .../services/config/CoselmarServicesConfig.java | 44 +++++++++++--- .../config/CoselmarServicesConfigOption.java | 15 +++++ .../coselmar/services/v1/UsersWebService.java | 31 +++++++++- coselmar-rest/src/main/resources/mapping | 4 +- .../src/main/webapp/js/coselmar-controllers.js | 11 +++- .../src/main/webapp/js/coselmar-user-services.js | 28 ++++----- pom.xml | 49 ++++++++++++++++ 13 files changed, 287 insertions(+), 33 deletions(-) diff --git a/coselmar-rest/pom.xml b/coselmar-rest/pom.xml index b58962c..9043d77 100644 --- a/coselmar-rest/pom.xml +++ b/coselmar-rest/pom.xml @@ -70,6 +70,10 @@ <artifactId>commons-beanutils</artifactId> </dependency> <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-email</artifactId> + </dependency> + <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> @@ -139,6 +143,48 @@ <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> + <dependency> + <groupId>org.nuiton.topia</groupId> + <artifactId>topia-junit</artifactId> + </dependency> + <dependency> + <groupId>org.debux.webmotion</groupId> + <artifactId>webmotion-unittest</artifactId> + <exclusions> + <exclusion> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-logging-juli</artifactId> + </exclusion> + <exclusion> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-jasper</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jdt.core.compiler</groupId> + <artifactId>ecj</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-core</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-jasper</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-logging-juli</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-logging-log4j</artifactId> + </dependency> </dependencies> diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java index 81246b8..d53648e 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java @@ -13,6 +13,7 @@ public class UserBean implements Serializable { protected String mail; protected String role; protected String qualification; + protected String password; public UserBean(String id, String firstName, String name, String mail, String role, String qualification) { this.id = id; @@ -70,4 +71,12 @@ public class UserBean implements Serializable { public void setQualification(String qualification) { this.qualification = qualification; } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarRestApplicationListener.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarRestApplicationListener.java index 830d82f..e16b7a3 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarRestApplicationListener.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarRestApplicationListener.java @@ -29,6 +29,7 @@ import java.util.Set; import com.google.common.collect.Sets; import fr.ifremer.coselmar.beans.DocumentBean; +import fr.ifremer.coselmar.beans.UserBean; import fr.ifremer.coselmar.converter.DateConverter; import fr.ifremer.coselmar.converter.JsonArrayConverter; import fr.ifremer.coselmar.converter.JsonConverter; @@ -44,7 +45,8 @@ import org.debux.webmotion.server.mapping.Mapping; public class CoselmarRestApplicationListener implements WebMotionServerListener { protected static final Set<Class<?>> BEAN_TYPES = Sets.<Class<?>>newHashSet( - DocumentBean.class + DocumentBean.class, + UserBean.class ); @Override diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarServicesContext.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarServicesContext.java index 2c4e793..43bc0a9 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarServicesContext.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarServicesContext.java @@ -50,11 +50,10 @@ public interface CoselmarServicesContext { String getCleanMail(String email); - //TODO ymartel : think about it with user management -// String generatePassword(); -// -// String generateSalt(); -// -// String encodePassword(String salt, String password); + String generatePassword(); + + String generateSalt(); + + String encodePassword(String salt, String password); } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarWebServiceSupport.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarWebServiceSupport.java index 9c9d514..386619f 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarWebServiceSupport.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/CoselmarWebServiceSupport.java @@ -105,4 +105,5 @@ public abstract class CoselmarWebServiceSupport extends WebMotionController impl public void rollback() { getPersistenceContext().rollback(); } + } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/DefaultCoselmarServicesContext.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/DefaultCoselmarServicesContext.java index bfa7c08..060e5b1 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/DefaultCoselmarServicesContext.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/DefaultCoselmarServicesContext.java @@ -26,19 +26,28 @@ package fr.ifremer.coselmar.services; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.Date; import java.util.Locale; import fr.ifremer.coselmar.persistence.CoselmarPersistenceContext; import fr.ifremer.coselmar.persistence.CoselmarTopiaApplicationContext; import fr.ifremer.coselmar.services.config.CoselmarServicesConfig; +import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; + +import static org.apache.commons.logging.LogFactory.getLog; /** * @author ymartel <martel@codelutin.com> */ public class DefaultCoselmarServicesContext implements CoselmarServicesContext { + private static final Log log = getLog(DefaultCoselmarServicesContext.class); + protected CoselmarServicesConfig servicesConfig; protected CoselmarPersistenceContext persistenceContext; @@ -123,4 +132,62 @@ public class DefaultCoselmarServicesContext implements CoselmarServicesContext { return email == null ? null : StringUtils.lowerCase(email.trim()); } + @Override + public String generateSalt() { + + SecureRandom secureRandom; + try { + secureRandom = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + secureRandom = new SecureRandom(); + } + byte[] salt = new byte[16]; + secureRandom.nextBytes(salt); + return salt.toString(); + } + + @Override + public String generatePassword() { + + return RandomStringUtils.randomAlphanumeric(8); + } + + @Override + public String encodePassword(String salt, String password) { + + String encodedPassword = getSecurePassword(salt, password, getCoselmarServicesConfig().getEncryptionAlgorithm()); + return encodedPassword; + } + + /** + * + * @param algorithm : Instance Type that will be loaded from MessageDigest, + * should be : MD5, SHA-1, SHA-256, SHA-384, SHA-512. + */ + protected static String getSecurePassword(String salt, String passwordToHash, String algorithm) { + + String generatedPassword; + + try { + MessageDigest digest = MessageDigest.getInstance(algorithm); + digest.update(salt.getBytes()); + byte[] passwordBytes = digest.digest(passwordToHash.getBytes()); + StringBuilder stringBuilder = new StringBuilder(); + for(int i=0; i < passwordBytes.length ;i++) + { + stringBuilder.append(Integer.toString((passwordBytes[i] & 0xff) + 0x100, 16).substring(1)); + } + generatedPassword = stringBuilder.toString(); + + } catch (NoSuchAlgorithmException e) { + String errorMessage = "Unable to encode password"; + if (log.isErrorEnabled()) { + log.error(errorMessage, e); + } + throw new CoselmarTechnicalException(errorMessage); + } + + return generatedPassword; + } + } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfig.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfig.java index fe2fae6..ffbd096 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfig.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfig.java @@ -59,7 +59,8 @@ public class CoselmarServicesConfig { if (defaultValues != null) { for (Map.Entry<Object, Object> entry : defaultValues.entrySet()) { - applicationConfig.setOption((String) entry.getKey(), (String) entry.getValue()); + applicationConfig.setOption((String) entry.getKey(), + (String) entry.getValue()); } } try { @@ -70,7 +71,8 @@ public class CoselmarServicesConfig { if (log.isInfoEnabled()) { StringBuilder builder = new StringBuilder("Coselmar configuration:"); builder.append("\nFilename: ").append(filename); - List<CoselmarServicesConfigOption> options = Lists.newArrayList(CoselmarServicesConfigOption.values()); + List<CoselmarServicesConfigOption> options = + Lists.newArrayList(CoselmarServicesConfigOption.values()); for (CoselmarServicesConfigOption option : options) { builder.append(String.format("\n%1$-40s = %2$s", option.getKey(), @@ -94,21 +96,49 @@ public class CoselmarServicesConfig { } public File getDataDirectory() { - return applicationConfig.getOptionAsFile(CoselmarServicesConfigOption.DATA_DIRECTORY.key); + return applicationConfig.getOptionAsFile( + CoselmarServicesConfigOption.DATA_DIRECTORY.key); + } + + /** + * @return Le nom d'hôte du serveur SMTP. + */ + public String getSmtpHost() { + return applicationConfig.getOption(CoselmarServicesConfigOption.SMTP_HOST.key); + } + + /** + * @return Le port du serveur SMTP. + */ + public int getSmtpPort() { + return applicationConfig.getOptionAsInt(CoselmarServicesConfigOption.SMTP_PORT.key); + } + + /** + * @return L'adresse d'expéditeur pour les mails de notifications + */ + public String getSmtpFrom() { + return applicationConfig.getOption(CoselmarServicesConfigOption.SMTP_FROM.key); } public boolean isLogConfigurationProvided() { - boolean logConfigurationProvided = - StringUtils.isNotBlank(applicationConfig.getOption(CoselmarServicesConfigOption.LOG_CONFIGURATION_FILE.key)); + boolean logConfigurationProvided = StringUtils.isNotBlank( + applicationConfig.getOption(CoselmarServicesConfigOption.LOG_CONFIGURATION_FILE.key)); return logConfigurationProvided; } public File getLogConfigurationFile() { - return applicationConfig.getOptionAsFile(CoselmarServicesConfigOption.LOG_CONFIGURATION_FILE.key); + return applicationConfig.getOptionAsFile( + CoselmarServicesConfigOption.LOG_CONFIGURATION_FILE.key); } public boolean isDevMode() { - boolean isDevMode = applicationConfig.getOptionAsBoolean(CoselmarServicesConfigOption.DEV_MODE.key); + boolean isDevMode = applicationConfig.getOptionAsBoolean( + CoselmarServicesConfigOption.DEV_MODE.key); return isDevMode; } + + public String getEncryptionAlgorithm() { + return "SHA-256"; + } } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfigOption.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfigOption.java index d616a55..3572f88 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfigOption.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfigOption.java @@ -40,6 +40,21 @@ public enum CoselmarServicesConfigOption implements ConfigOptionDef { "${java.io.tmpdir}/coselmar", File.class), + SMTP_HOST( + "coselmar.smtp.host", + "Nom d'hôte du serveur SMTP", + "", String.class), + + SMTP_PORT( + "coselmar.smtp.port", + "Le port du serveur SMTP", + "25", Integer.class), + + SMTP_FROM( + "coselmar.smtp.from", + "L'adresse d'expéditeur pour les mails de notifications", + "", String.class), + LOG_CONFIGURATION_FILE( "coselmar.logConfigurationFile", "Path to the logs config file", 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 3add9f3..14590be 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 @@ -9,6 +9,7 @@ import fr.ifremer.coselmar.converter.BeanEntityConverter; import fr.ifremer.coselmar.persistence.entity.User; import fr.ifremer.coselmar.persistence.entity.UserRole; import fr.ifremer.coselmar.services.CoselmarWebServiceSupport; +import fr.ifremer.coselmar.services.errors.InvalidCredentialException; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; @@ -57,21 +58,49 @@ public class UsersWebService extends CoselmarWebServiceSupport { userEntity.setFirstname(user.getFirstName()); userEntity.setName(user.getName()); - userEntity.setMail(user.getMail()); + String mail = getCleanMail(user.getMail()); + userEntity.setMail(mail); userEntity.setRole(UserRole.valueOf(user.getRole().toUpperCase())); userEntity.setQualification(user.getQualification()); + String password = user.getPassword(); + if (StringUtils.isBlank(password)) { + password = getServicesContext().generatePassword(); + } + //generate a password & a salt + String salt = getServicesContext().generateSalt(); + String encodedPassword = getServicesContext().encodePassword(salt, password); + userEntity.setPassword(encodedPassword); + userEntity.setSalt(salt); commit(); // send mail to user with password + + + } public void changePassword() { //TODO ymartel } + public void login(String mail, String password) throws InvalidCredentialException { + Preconditions.checkNotNull(mail); + Preconditions.checkNotNull(password); + + User user = getUserDao().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"); + } + + } + public void deleteUser(String userId) { // reconstitute full id diff --git a/coselmar-rest/src/main/resources/mapping b/coselmar-rest/src/main/resources/mapping index d18f439..a84b4c0 100644 --- a/coselmar-rest/src/main/resources/mapping +++ b/coselmar-rest/src/main/resources/mapping @@ -14,7 +14,8 @@ default.render=fr.ifremer.coselmar.services.CoselmarRender [errors] -#fr.ifremer.coselmar.services.errors.CoselmarUnauthorizedException ErrorAction.on403 +#fr.ifremer.coselmar.services.errors.InvalidCredentialException ErrorAction.on401 +#fr.ifremer.coselmar.services.errors.UnauthorizedException ErrorAction.on403 #fr.ifremer.coselmar.services.CoselmarTechnicalException ErrorAction.on500 #org.nuiton.topia.persistence.TopiaNoResultException ErrorAction.on404 @@ -39,4 +40,5 @@ GET /v1/users UsersWebService.getUsers GET /v1/users/{userId} UsersWebService.getUser POST /v1/users UsersWebService.addUser DELETE /v1/users/{userId} UsersWebService.deleteUser +POST /v1/login UsersWebService.login diff --git a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js index 5e5a756..02575e1 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js @@ -143,14 +143,19 @@ coselmarControllers.controller("UsersCtrl", ['$scope', '$route', '$routeParams', // Controller for new user View -coselmarControllers.controller("NewUserCtrl", ['$scope', '$route', 'userService', function($scope, $route, userService){ +coselmarControllers.controller("NewUserCtrl", ['$scope', '$route', '$location', 'userService', function($scope, $route, $location, userService){ + + $scope.user = {'role' : 'expert'}; $scope.createNewUser = function(){ -// var user = {'privacy':$scope.privacy, 'role':'expert'}; // Call service to create a new user - userService.createUser($scope.user, $scope, function() { + userService.createUser($scope.user, function() { $location.path("/users"); + },function(error) { + //TODO ymartel 20141118 : deal with error.status or statusText + console.log("error occurs"); + console.log(error.s); }); // Reload the page 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 5ff11d0..c52e69a 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-user-services.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-user-services.js @@ -32,22 +32,22 @@ function User(resource){ this.resource = resource; // this.baseURL = "v1/users"; - this.createUser = function(user, scope, successFunction){ + this.createUser = function(user, successFunction, failFunction){ + + var formData = new FormData(); + formData.append("user", JSON.stringify(user)); -// var formData = new FormData(); -// formData.append("user", JSON.stringify(user)); // Save the User - var userResource = resource(baseURL, {user:user}); -// var userResource = resource(baseURL, null, { -// 'save': { -// method:'POST', -// transformRequest: angular.identity, -// headers:{ -// 'Content-Type':undefined -// } -// } -// }); - userResource.save({user:user}, successFunction); + var userResource = resource(baseURL, null, { + 'save': { + method:'POST', + transformRequest: angular.identity, + headers:{ + 'Content-Type': undefined + } + } + }); + userResource.save(null, formData, successFunction, failFunction); } this.getUser = function(id, scope){ diff --git a/pom.xml b/pom.xml index a11ecaa..57123ee 100644 --- a/pom.xml +++ b/pom.xml @@ -143,6 +143,8 @@ <postgresqlVersion>9.1-901-1.jdbc4</postgresqlVersion> <h2Version>1.4.178</h2Version> + <tomcatEmbedVersion>7.0.50</tomcatEmbedVersion> + </properties> @@ -270,6 +272,11 @@ <version>1.9.2</version> </dependency> <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-email</artifactId> + <version>1.3.2</version> + </dependency> + <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> @@ -350,6 +357,48 @@ <version>4.11</version> <scope>test</scope> </dependency> + <dependency> + <groupId>org.nuiton.topia</groupId> + <artifactId>topia-junit</artifactId> + <version>${topiaVersion}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.debux.webmotion</groupId> + <artifactId>webmotion-unittest</artifactId> + <version>${webmotionVersion}</version> + <scope>test</scope> + </dependency> + + + <!-- for embedded test --> + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-core</artifactId> + <version>${tomcatEmbedVersion}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-logging-juli</artifactId> + <version>${tomcatEmbedVersion}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-logging-log4j</artifactId> + <version>${tomcatEmbedVersion}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.tomcat.embed</groupId> + <artifactId>tomcat-embed-jasper</artifactId> + <version>${tomcatEmbedVersion}</version> + <scope>provided</scope> + </dependency> </dependencies> -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
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 0eaf8f5e894f766dc6e4cafd35efe526321ad447 Author: Yannick Martel <martel@©odelutin.com> Date: Tue Nov 18 18:13:26 2014 +0100 prepare user account creation and login operrations --- .../errors/InvalidCredentialException.java | 11 + .../services/AbstractCoselmarWebServiceTest.java | 92 +++++++++ .../services/FakeCoselmarApplicationContext.java | 224 +++++++++++++++++++++ .../services/FakeCoselmarServicesContext.java | 51 +++++ .../coselmar/services/UsersWebServiceTest.java | 46 +++++ 5 files changed, 424 insertions(+) diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/errors/InvalidCredentialException.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/errors/InvalidCredentialException.java new file mode 100644 index 0000000..a0c89eb --- /dev/null +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/errors/InvalidCredentialException.java @@ -0,0 +1,11 @@ +package fr.ifremer.coselmar.services.errors; + +/** + * @author ymartel (martel@codelutin.com) + */ +public class InvalidCredentialException extends Exception { + + public InvalidCredentialException(String message) { + super(message); + } +} diff --git a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/AbstractCoselmarWebServiceTest.java b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/AbstractCoselmarWebServiceTest.java new file mode 100644 index 0000000..b15688a --- /dev/null +++ b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/AbstractCoselmarWebServiceTest.java @@ -0,0 +1,92 @@ +package fr.ifremer.coselmar.services; + +import java.io.File; +import java.io.IOException; +import java.util.Locale; + +import fr.ifremer.coselmar.persistence.CoselmarPersistenceContext; +import org.apache.commons.logging.Log; +import org.debux.webmotion.unittest.WebMotionTest; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.nuiton.util.DateUtil; + +import static org.apache.commons.logging.LogFactory.getLog; + +/** + * @author ymartel <martel@codelutin.com> + */ +public class AbstractCoselmarWebServiceTest extends WebMotionTest { + + private static final Log log = getLog(AbstractCoselmarWebServiceTest.class); + + @Rule + public final FakeCoselmarApplicationContext application = new FakeCoselmarApplicationContext("coselmar-services.properties"); + + @Override + protected int getPort() { + return application.getPort(); + } + + @Before + public void startServer() throws Exception { + + CoselmarServicesApplicationContext applicationContext = + new CoselmarServicesApplicationContext(application.getApplicationConfig(), + application.getTopiaApplicationContext()) { + + @Override + public CoselmarServicesContext newServiceContext(CoselmarPersistenceContext persistenceContext, Locale locale) { + + FakeCoselmarServicesContext servicesContext = FakeCoselmarServicesContext.newServiceContext( + DateUtil.createDate(1, 1, 2014), + Locale.FRANCE, + application.getApplicationConfig(), + application.getTopiaApplicationContext(), + application.newPersistenceContext()); + return servicesContext; + + } + + }; + + applicationContext.init(); + + CoselmarServicesApplicationContext.setApplicationContext(applicationContext); + + super.startServer(); + + } + + @Override + protected String getServerBaseDirectory() { + + return new File(application.getTestBasedir(), + "tomcat_" + application.getPort()).getAbsolutePath(); + + } + + @After + public void stopServer() throws Exception { + + if (log.isTraceEnabled()) { + log.trace("closing application context " + application); + } + + application.close(); + server.stop(); + server.destroy(); + + } + + protected void showTestResult(String content) throws IOException { + + String testName = application.getMethodName(); + + if (log.isInfoEnabled()) { + log.info("test *" + testName + "* result\n" + content); + } + + } +} diff --git a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/FakeCoselmarApplicationContext.java b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/FakeCoselmarApplicationContext.java new file mode 100644 index 0000000..50509f9 --- /dev/null +++ b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/FakeCoselmarApplicationContext.java @@ -0,0 +1,224 @@ +package fr.ifremer.coselmar.services; + +import java.io.File; +import java.io.IOException; +import java.net.ServerSocket; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicInteger; + +import fr.ifremer.coselmar.persistence.CoselmarPersistenceContext; +import fr.ifremer.coselmar.persistence.CoselmarTopiaApplicationContext; +import fr.ifremer.coselmar.persistence.CoselmarTopiaPersistenceContext; +import fr.ifremer.coselmar.services.config.CoselmarServicesConfig; +import fr.ifremer.coselmar.services.config.CoselmarServicesConfigOption; +import org.apache.commons.logging.Log; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; +import org.nuiton.topia.junit.ConfigurationHelper; +import org.nuiton.util.DateUtil; + +import static org.apache.commons.logging.LogFactory.getLog; + + +/** + * @author ymartel <martel@codelutin.com> + */ +public class FakeCoselmarApplicationContext extends TestWatcher implements CoselmarApplicationContext { + + private static Log log = getLog(FakeCoselmarApplicationContext.class); + + protected static AtomicInteger portNumberCounter = new AtomicInteger(9999); + + protected File testBasedir; + + protected List<CoselmarTopiaPersistenceContext> openedTransactions = new LinkedList<>(); + + protected CoselmarTopiaApplicationContext applicationContext; + + protected CoselmarServicesConfig configuration; + + protected String methodName; + + protected int currentPortNumber; + + protected final String configurationPath; + + public FakeCoselmarApplicationContext(String configurationPath) { + this.configurationPath = configurationPath; + } + + @Override + protected void starting(Description description) { + + // get an available port + currentPortNumber = getAvailablePort(); + if (log.isDebugEnabled()) { + log.debug("Using port: " + currentPortNumber); + } + + methodName = description.getMethodName(); + + // get test directory + testBasedir = ConfigurationHelper.getTestSpecificDirectory( + description.getTestClass(), + description.getMethodName()); + + if (log.isDebugEnabled()) { + log.debug("testBasedir: " + testBasedir); + } + + init(); + + } + + @Override + public void finished(Description description) { + + close(); + } + + @Override + public void init() { + + // --- create configuration --- // + + Properties defaultvalues = new Properties(); + defaultvalues.put(CoselmarServicesConfigOption.DATA_DIRECTORY.getKey(), testBasedir.getAbsolutePath()); + + configuration = new CoselmarServicesConfig(configurationPath, defaultvalues); + + // --- create topia application context --- // + + Map<String, String> topiaProperties = configuration.getTopiaProperties(); + applicationContext = new CoselmarTopiaApplicationContext(topiaProperties); + + } + + @Override + public void close() { + + if (applicationContext != null && !applicationContext.isClosed()) { + + for (CoselmarTopiaPersistenceContext openedTransaction : openedTransactions) { + + if (log.isTraceEnabled()) { + log.trace("closing transaction " + openedTransaction); + } + + if (!openedTransaction.isClosed()) { + + openedTransaction.close(); + + } + + } + + if (log.isTraceEnabled()) { + log.trace("closing transaction " + applicationContext); + } + + applicationContext.close(); + + } + } + + @Override + public CoselmarTopiaApplicationContext getTopiaApplicationContext() { + return applicationContext; + } + + @Override + public CoselmarServicesConfig getApplicationConfig() { + return configuration; + } + + @Override + public CoselmarTopiaPersistenceContext newPersistenceContext() { + + CoselmarTopiaPersistenceContext persistenceContext; + + persistenceContext = applicationContext.newPersistenceContext(); + + if (log.isTraceEnabled()) { + log.trace("opened transaction " + persistenceContext); + } + + openedTransactions.add(persistenceContext); + + return persistenceContext; + + } + + @Override + public FakeCoselmarServicesContext newServiceContext(CoselmarPersistenceContext persistenceContext, Locale locale) { + + FakeCoselmarServicesContext serviceContext = FakeCoselmarServicesContext.newServiceContext( + DateUtil.createDate(1, 1, 2014), + Locale.FRANCE, + getApplicationConfig(), + getTopiaApplicationContext(), + newPersistenceContext()); + return serviceContext; + + } + + public File getTestBasedir() { + return testBasedir; + } + + public int getPort() { + return currentPortNumber; + } + + public String getMethodName() { + return methodName; + } + + protected int getAvailablePort() { + + int port = portNumberCounter.getAndIncrement(); + + boolean portTaken = false; + ServerSocket socket = null; + + try { + + socket = new ServerSocket(port); + + } catch (IOException e) { + + portTaken = true; + + } finally { + + if (socket != null) + + try { + + socket.close(); + + } catch (IOException e) { + + if (log.isDebugEnabled()) { + log.debug("Already used port: " + port); + } + + } + + } + + if (portTaken) { + + port = getAvailablePort(); + + } + + return port; + + } + +} diff --git a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/FakeCoselmarServicesContext.java b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/FakeCoselmarServicesContext.java new file mode 100644 index 0000000..d7af8a8 --- /dev/null +++ b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/FakeCoselmarServicesContext.java @@ -0,0 +1,51 @@ +package fr.ifremer.coselmar.services; + +import java.util.Date; +import java.util.Locale; + +import com.google.common.base.Preconditions; +import fr.ifremer.coselmar.persistence.CoselmarTopiaApplicationContext; +import fr.ifremer.coselmar.persistence.CoselmarTopiaPersistenceContext; +import fr.ifremer.coselmar.services.config.CoselmarServicesConfig; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author ymartel <martel@codelutin.com> + */ +public class FakeCoselmarServicesContext extends DefaultCoselmarServicesContext { + + private static final Log log = + LogFactory.getLog(FakeCoselmarServicesContext.class); + + protected Date date; + + + public static FakeCoselmarServicesContext newServiceContext(Date now, + Locale locale, + CoselmarServicesConfig serviceConfig, + CoselmarTopiaApplicationContext applicationcontext, + CoselmarTopiaPersistenceContext persistenceContext) { + + FakeCoselmarServicesContext serviceContext = new FakeCoselmarServicesContext(); + serviceContext.setPersistenceContext(persistenceContext); + serviceContext.setCoselmarServicesConfig(serviceConfig); + serviceContext.setTopiaApplicationContext(applicationcontext); + serviceContext.setLocale(locale); + serviceContext.setDate(now); + return serviceContext; + } + + @Override + public Date getNow() { + Preconditions.checkState(date != null, "you must provide a date before running service test"); + if (log.isTraceEnabled()) { + log.trace("injecting fake date in service: " + date); + } + return date; + } + + public void setDate(Date date) { + this.date = date; + } +} diff --git a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/UsersWebServiceTest.java b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/UsersWebServiceTest.java new file mode 100644 index 0000000..cb50372 --- /dev/null +++ b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/UsersWebServiceTest.java @@ -0,0 +1,46 @@ +package fr.ifremer.coselmar.services; + +import java.util.Locale; + +import org.apache.http.client.fluent.Request; +import org.apache.http.client.fluent.Response; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author ymartel <martel@codelutin.com> + */ +public class UsersWebServiceTest extends AbstractCoselmarWebServiceTest { + + protected FakeCoselmarServicesContext serviceContext; + + protected FakeCoselmarServicesContext getServiceContext() { + + if (serviceContext == null) { + serviceContext = application.newServiceContext(application.newPersistenceContext(), Locale.FRANCE); + } + + return serviceContext; + } + + @Test + public void testAuthentication() throws Exception { + + Request addUserRequest = createRequest("/v1/users") + .addParameter("user", "{firstName: 'test', name: 'her', mail: 'test@test.org', role: 'supervisor', qualification: 'unit tester', password : 'iamatester'}") + .Post(); + + String content = addUserRequest.execute().returnContent().asString(); + showTestResult(content); + Assert.assertNotNull(content); + + Request loginRequest = createRequest("/v1/login") + .addParameter("mail", "test@test.org") + .addParameter("password", "iamatester") + .Post(); + + Response loginResponse = loginRequest.execute(); + Assert.assertEquals(200, loginResponse.returnResponse().getStatusLine().getStatusCode()); + + } +} -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
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 bc986faef0b94cd4c224056157bdc160875f1f19 Author: Yannick Martel <martel@©odelutin.com> Date: Wed Nov 19 11:21:40 2014 +0100 prepare mail support --- .../coselmar/beans/CoselmarRegistrationMail.java | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/CoselmarRegistrationMail.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/CoselmarRegistrationMail.java new file mode 100644 index 0000000..80a0adb --- /dev/null +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/CoselmarRegistrationMail.java @@ -0,0 +1,79 @@ +package fr.ifremer.coselmar.beans; + +import java.util.Locale; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.nuiton.i18n.I18n; + +/** + * @author ymartel <martel@codelutin.com> + */ +public class CoselmarRegistrationMail { + + protected Locale locale; + + protected String to; + + private UserBean user; + + private String coselmarUrl; + private String password; + + public CoselmarRegistrationMail(Locale locale) { + this.locale = locale; + } + + public Locale getLocale() { + return locale; + } + + public String getTo() { + return to; + } + + public void addTo(String mail) { + this.to = mail; + } + + public String getSubject() { + if (user.getName() == null) { + return I18n.l(locale, "coselmar.service.mail.UserAccountCreatedEmail.subject", user.getMail()); + } + return I18n.l(locale, "coselmar.service.mail.UserAccountCreatedEmail.subject", user.getName()); + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this); + } + + public boolean isRecipientProvided() { + boolean isRecipientProvided = StringUtils.isNotBlank(this.to); + return isRecipientProvided; + } + + public UserBean getUser() { + return user; + } + + public void setUser(UserBean user) { + this.user = user; + } + + public String getCoselmarUrl() { + return coselmarUrl; + } + + public void setCoselmarUrl(String coselmarUrl) { + this.coselmarUrl = coselmarUrl; + } + + public String getPassword () { + return password; + } + + public void setPassword (String password) { + this.password = password; + } +} -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
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 310cf01e356ed292016809cbc0c7e388266f06a7 Author: Yannick Martel <martel@©odelutin.com> Date: Thu Nov 20 14:49:26 2014 +0100 add organization in user --- .gitignore | 3 ++- .../src/main/xmi/coselmar-model.zargo | Bin 5991 -> 6024 bytes .../main/java/fr/ifremer/coselmar/beans/UserBean.java | 12 +++++++++++- .../coselmar/converter/BeanEntityConverter.java | 3 ++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 62f7843..6b8f51b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,11 +9,12 @@ /*/*.ipr /*.iws /*/*.iws -/*/*~ +/**/*~ /.project /*/.project /.classpath /*/.classpath /.settings /*/.settings +/*/*.zargo~ diff --git a/coselmar-persistence/src/main/xmi/coselmar-model.zargo b/coselmar-persistence/src/main/xmi/coselmar-model.zargo index 0ddcf03..bcd73e2 100644 Binary files a/coselmar-persistence/src/main/xmi/coselmar-model.zargo and b/coselmar-persistence/src/main/xmi/coselmar-model.zargo differ diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java index d53648e..4bc9260 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserBean.java @@ -13,15 +13,17 @@ public class UserBean implements Serializable { protected String mail; protected String role; protected String qualification; + protected String organization; protected String password; - public UserBean(String id, String firstName, String name, String mail, String role, String qualification) { + public UserBean(String id, String firstName, String name, String mail, String role, String qualification, String organization) { this.id = id; this.firstName = firstName; this.name = name; this.mail = mail; this.role = role; this.qualification = qualification; + this.organization = organization; } public String getId() { @@ -72,6 +74,14 @@ public class UserBean implements Serializable { this.qualification = qualification; } + public String getOrganization() { + return organization; + } + + public void setOrganization(String organization) { + this.organization = organization; + } + public String getPassword() { return password; } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java index d90136e..5475788 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/converter/BeanEntityConverter.java @@ -55,7 +55,8 @@ public class BeanEntityConverter { user.getName(), user.getMail(), user.getRole().name(), - user.getQualification()); + user.getQualification(), + user.getOrganization()); } } -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
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 a6e1f56d663bf878bd9fb49f7995227233f1ff6d Author: Yannick Martel <martel@©odelutin.com> Date: Fri Nov 21 11:13:21 2014 +0100 finish user creation, add login method --- coselmar-rest/pom.xml | 13 +++ ...rationMail.java => UserAccountCreatedMail.java} | 12 +- .../services/config/CoselmarServicesConfig.java | 4 + .../config/CoselmarServicesConfigOption.java | 26 +++-- .../coselmar/services/v1/UsersWebService.java | 126 ++++++++++++++++++++- .../resources/mail/UserAccountCreatedMail.mustache | 8 ++ .../mail/UserAccountCreatedMail_fr.mustache | 8 ++ .../services/AbstractCoselmarWebServiceTest.java | 2 +- .../coselmar/services/UsersWebServiceTest.java | 21 +++- .../src/test/resources/coselmar-test.properties | 33 ++++++ pom.xml | 7 ++ 11 files changed, 235 insertions(+), 25 deletions(-) diff --git a/coselmar-rest/pom.xml b/coselmar-rest/pom.xml index 9043d77..07686e7 100644 --- a/coselmar-rest/pom.xml +++ b/coselmar-rest/pom.xml @@ -127,6 +127,13 @@ </dependency> <dependency> + <groupId>com.auth0</groupId> + <artifactId>java-jwt</artifactId> + <version>1.0.0</version> + </dependency> + + <!-- databases --> + <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> @@ -138,6 +145,12 @@ <scope>runtime</scope> </dependency> + <!-- Others --> + <dependency> + <groupId>com.github.spullara.mustache.java</groupId> + <artifactId>compiler</artifactId> + </dependency> + <!-- Tests --> <dependency> <groupId>junit</groupId> diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/CoselmarRegistrationMail.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserAccountCreatedMail.java similarity index 81% rename from coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/CoselmarRegistrationMail.java rename to coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserAccountCreatedMail.java index 80a0adb..4c82196 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/CoselmarRegistrationMail.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/UserAccountCreatedMail.java @@ -2,6 +2,7 @@ package fr.ifremer.coselmar.beans; import java.util.Locale; +import com.google.common.base.Strings; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.nuiton.i18n.I18n; @@ -9,7 +10,7 @@ import org.nuiton.i18n.I18n; /** * @author ymartel <martel@codelutin.com> */ -public class CoselmarRegistrationMail { +public class UserAccountCreatedMail { protected Locale locale; @@ -20,7 +21,7 @@ public class CoselmarRegistrationMail { private String coselmarUrl; private String password; - public CoselmarRegistrationMail(Locale locale) { + public UserAccountCreatedMail(Locale locale) { this.locale = locale; } @@ -32,15 +33,16 @@ public class CoselmarRegistrationMail { return to; } - public void addTo(String mail) { + public void setTo(String mail) { this.to = mail; } public String getSubject() { - if (user.getName() == null) { + String fullname = Strings.nullToEmpty(user.getFirstName()) + " " + Strings.nullToEmpty(user.getName()); + if (StringUtils.isBlank(fullname)) { return I18n.l(locale, "coselmar.service.mail.UserAccountCreatedEmail.subject", user.getMail()); } - return I18n.l(locale, "coselmar.service.mail.UserAccountCreatedEmail.subject", user.getName()); + return I18n.l(locale, "coselmar.service.mail.UserAccountCreatedEmail.subject", fullname); } @Override diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfig.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfig.java index ffbd096..2ced2d9 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfig.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfig.java @@ -138,6 +138,10 @@ public class CoselmarServicesConfig { return isDevMode; } + public String getWebSecurityKey() { + return applicationConfig.getOption(CoselmarServicesConfigOption.WEB_SECURITY_KEY.key); + } + public String getEncryptionAlgorithm() { return "SHA-256"; } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfigOption.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfigOption.java index 3572f88..720f302 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfigOption.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/config/CoselmarServicesConfigOption.java @@ -35,10 +35,10 @@ import org.nuiton.i18n.I18n; public enum CoselmarServicesConfigOption implements ConfigOptionDef { DATA_DIRECTORY( - "coselmar.data.directory", - I18n.n("coselmar.configuration.data.directory"), - "${java.io.tmpdir}/coselmar", - File.class), + "coselmar.data.directory", + I18n.n("coselmar.configuration.data.directory"), + "${java.io.tmpdir}/coselmar", + File.class), SMTP_HOST( "coselmar.smtp.host", @@ -56,15 +56,19 @@ public enum CoselmarServicesConfigOption implements ConfigOptionDef { "", String.class), LOG_CONFIGURATION_FILE( - "coselmar.logConfigurationFile", - "Path to the logs config file", - null, - String.class), + "coselmar.logConfigurationFile", + "Path to the logs config file", + null, String.class), DEV_MODE( - "pollen.devMode", - "Mode développement, court-circuite l'envoi de mail", - "true", Boolean.class), + "coselmar.devMode", + "Mode développement, court-circuite l'envoi de mail", + "true", Boolean.class), + + WEB_SECURITY_KEY( + "coselmar.web.security.key", + "Clef de sécurity permettant d'encoder les token d'authentication", + "iamageek,r3477y", String.class), ; protected final String key; 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 14590be..433c7c4 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 @@ -1,17 +1,35 @@ package fr.ifremer.coselmar.services.v1; +import java.io.StringWriter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; - +import java.util.Locale; +import java.util.Map; + +import com.auth0.jwt.Algorithm; +import com.auth0.jwt.JWTSigner; +import com.github.mustachejava.DefaultMustacheFactory; +import com.github.mustachejava.Mustache; +import com.github.mustachejava.MustacheException; +import com.github.mustachejava.MustacheFactory; import com.google.common.base.Preconditions; +import fr.ifremer.coselmar.beans.UserAccountCreatedMail; import fr.ifremer.coselmar.beans.UserBean; import fr.ifremer.coselmar.converter.BeanEntityConverter; import fr.ifremer.coselmar.persistence.entity.User; import fr.ifremer.coselmar.persistence.entity.UserRole; +import fr.ifremer.coselmar.services.CoselmarTechnicalException; import fr.ifremer.coselmar.services.CoselmarWebServiceSupport; +import fr.ifremer.coselmar.services.config.CoselmarServicesConfig; import fr.ifremer.coselmar.services.errors.InvalidCredentialException; +import org.apache.commons.io.Charsets; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; +import org.apache.commons.mail.Email; +import org.apache.commons.mail.EmailException; +import org.apache.commons.mail.SimpleEmail; +import org.debux.webmotion.server.render.Render; import static org.apache.commons.logging.LogFactory.getLog; @@ -77,16 +95,19 @@ public class UsersWebService extends CoselmarWebServiceSupport { commit(); // send mail to user with password + UserAccountCreatedMail userAccountCreatedMail = new UserAccountCreatedMail(getServicesContext().getLocale()); + userAccountCreatedMail.setUser(user); + userAccountCreatedMail.setPassword(password); + userAccountCreatedMail.setTo(user.getMail()); - - + sendMail(userAccountCreatedMail); } public void changePassword() { //TODO ymartel } - public void login(String mail, String password) throws InvalidCredentialException { + public Render login(String mail, String password) throws InvalidCredentialException { Preconditions.checkNotNull(mail); Preconditions.checkNotNull(password); @@ -99,6 +120,22 @@ public class UsersWebService extends CoselmarWebServiceSupport { throw new InvalidCredentialException("Invalid password given"); } + // return a Json Web Token for authentication + JWTSigner jwtSigner = new JWTSigner(getCoselmarServicesConfig().getWebSecurityKey()); + JWTSigner.Options signerOption = new JWTSigner.Options(); + signerOption.setAlgorithm(Algorithm.HS512); + + Map<String, Object> claims = new HashMap<>(); + String userTopiaId = user.getTopiaId(); + String shortId = getPersistenceContext().getTopiaIdFactory().getRandomPart(userTopiaId); + claims.put("userId", shortId); + claims.put("userFirstName", user.getFirstname()); + claims.put("userName", user.getName()); + claims.put("userRole", user.getRole()); + String webToken = jwtSigner.sign(claims, signerOption); + + return renderJSON("jwt", webToken); + } public void deleteUser(String userId) { @@ -111,4 +148,85 @@ public class UsersWebService extends CoselmarWebServiceSupport { commit(); } + + + ///////////////////////////////////////////// + /////////////// MAIL PART /////////////// + ///////////////////////////////////////////// + + protected void sendMail(UserAccountCreatedMail mail) { + + if (getCoselmarServicesConfig().isDevMode()) { + + if (log.isInfoEnabled()) { + log.info("an email should have been sent if not in devMode: to = " + + mail.getTo() + ". subject = '" + mail.getSubject() + + "'. body = \n" + getBody(mail)); + } + + if (!mail.isRecipientProvided() && log.isWarnEnabled()) { + log.warn("email has no recipient, would not have been sent " + mail); + } + + } else { + + CoselmarServicesConfig applicationConfig = getCoselmarServicesConfig(); + + String body = getBody(mail); + + if (mail.isRecipientProvided()) { + + Email newEmail = new SimpleEmail(); + newEmail.setHostName(applicationConfig.getSmtpHost()); + newEmail.setSmtpPort(applicationConfig.getSmtpPort()); + newEmail.setCharset(Charsets.UTF_8.name()); + newEmail.setSubject(mail.getSubject()); + + try { + newEmail.setFrom(applicationConfig.getSmtpFrom()); + String to = mail.getTo(); + newEmail.addTo(to); + newEmail.setMsg(body); + + newEmail.send(); + + } catch (EmailException e) { + throw new CoselmarTechnicalException(e); + } + + } else { + if (log.isErrorEnabled()) { + log.error("email has no recipient, won't be sent " + mail); + } + } + } + } + + protected String getBody(UserAccountCreatedMail mail) { + + Mustache mustache = getMustache(mail); + StringWriter stringWriter = new StringWriter(); + mustache.execute(stringWriter, mail); + + return stringWriter.toString(); + } + + protected Mustache getMustache(UserAccountCreatedMail mail) { + + MustacheFactory mustacheFactory = new DefaultMustacheFactory("mail/"); + Locale locale = mail.getLocale(); + String templateName = mail.getClass().getSimpleName() + "_" + locale.getLanguage() + ".mustache"; + + Mustache mustache; + try { + mustache = mustacheFactory.compile(templateName); + + } catch (MustacheException e) { + // fallback with no locale + templateName = mail.getClass().getSimpleName() + ".mustache"; + mustache = mustacheFactory.compile(templateName); + } + + return mustache; + } } diff --git a/coselmar-rest/src/main/resources/mail/UserAccountCreatedMail.mustache b/coselmar-rest/src/main/resources/mail/UserAccountCreatedMail.mustache new file mode 100644 index 0000000..10265c0 --- /dev/null +++ b/coselmar-rest/src/main/resources/mail/UserAccountCreatedMail.mustache @@ -0,0 +1,8 @@ +Welcome {{user.name}}, + +An account has been created for you on the web application Coselmar. + +Email: {{user.email}} +Password: {{password}} + +You can now access to your account by logging on the <a href="{{coselmarUrl}}">Coselmar</a> website. \ No newline at end of file diff --git a/coselmar-rest/src/main/resources/mail/UserAccountCreatedMail_fr.mustache b/coselmar-rest/src/main/resources/mail/UserAccountCreatedMail_fr.mustache new file mode 100644 index 0000000..ec531e4 --- /dev/null +++ b/coselmar-rest/src/main/resources/mail/UserAccountCreatedMail_fr.mustache @@ -0,0 +1,8 @@ +Bonjour {{user.name}}, + +Un compte vous a été ouvert sur l'application Coselmar. + +Courriel: {{user.email}} +Password: {{password}} + +Vous pouvez dès à présent accéder à l'application en vous connectant sur <a href="{{coselmarUrl}}">Coselmar</a>. \ No newline at end of file diff --git a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/AbstractCoselmarWebServiceTest.java b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/AbstractCoselmarWebServiceTest.java index b15688a..7a795f1 100644 --- a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/AbstractCoselmarWebServiceTest.java +++ b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/AbstractCoselmarWebServiceTest.java @@ -22,7 +22,7 @@ public class AbstractCoselmarWebServiceTest extends WebMotionTest { private static final Log log = getLog(AbstractCoselmarWebServiceTest.class); @Rule - public final FakeCoselmarApplicationContext application = new FakeCoselmarApplicationContext("coselmar-services.properties"); + public final FakeCoselmarApplicationContext application = new FakeCoselmarApplicationContext("coselmar-test.properties"); @Override protected int getPort() { diff --git a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/UsersWebServiceTest.java b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/UsersWebServiceTest.java index cb50372..0cb2cc4 100644 --- a/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/UsersWebServiceTest.java +++ b/coselmar-rest/src/test/java/fr/ifremer/coselmar/services/UsersWebServiceTest.java @@ -1,7 +1,12 @@ package fr.ifremer.coselmar.services; import java.util.Locale; +import java.util.Map; +import com.auth0.jwt.JWTVerifier; +import com.google.gson.Gson; +import org.apache.commons.codec.binary.Base64; +import org.apache.http.HttpResponse; import org.apache.http.client.fluent.Request; import org.apache.http.client.fluent.Response; import org.junit.Assert; @@ -30,9 +35,8 @@ public class UsersWebServiceTest extends AbstractCoselmarWebServiceTest { .addParameter("user", "{firstName: 'test', name: 'her', mail: 'test@test.org', role: 'supervisor', qualification: 'unit tester', password : 'iamatester'}") .Post(); - String content = addUserRequest.execute().returnContent().asString(); - showTestResult(content); - Assert.assertNotNull(content); + HttpResponse addUserResponse = addUserRequest.execute().returnResponse(); + Assert.assertEquals(200, addUserResponse.getStatusLine().getStatusCode()); Request loginRequest = createRequest("/v1/login") .addParameter("mail", "test@test.org") @@ -40,7 +44,16 @@ public class UsersWebServiceTest extends AbstractCoselmarWebServiceTest { .Post(); Response loginResponse = loginRequest.execute(); - Assert.assertEquals(200, loginResponse.returnResponse().getStatusLine().getStatusCode()); + String loginContent = loginResponse.returnContent().asString(); + Assert.assertNotNull(loginContent); + showTestResult(loginContent); + Gson gson = new Gson(); + Map<String, String> map = gson.fromJson(loginContent, Map.class); + + String webSecurityKey = getServiceContext().getCoselmarServicesConfig().getWebSecurityKey(); + JWTVerifier jwtVerifier = new JWTVerifier(Base64.encodeBase64String(webSecurityKey.getBytes("utf8")), "audience"); + String token = map.get("jwt"); + jwtVerifier.verify(token); } } diff --git a/coselmar-rest/src/test/resources/coselmar-test.properties b/coselmar-rest/src/test/resources/coselmar-test.properties new file mode 100644 index 0000000..abd3051 --- /dev/null +++ b/coselmar-rest/src/test/resources/coselmar-test.properties @@ -0,0 +1,33 @@ +### +# #%L +# Coselmar :: Rest Services +# $Id:$ +# $HeadURL:$ +# %% +# Copyright (C) 2014 Ifremer, Code Lutin +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/gpl-3.0.html>. +# #L% +### + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.connection.url=jdbc:h2:file:${coselmar.data.directory}/db/coselmar +hibernate.connection.username=sa +hibernate.connection.password=sa +hibernate.connection.driver_class=org.h2.Driver +hibernate.hbm2ddl.auto=update + +coselmar.devMode=true +coselmar.version=${project.version} diff --git a/pom.xml b/pom.xml index 57123ee..e2a1f04 100644 --- a/pom.xml +++ b/pom.xml @@ -337,6 +337,13 @@ <version>${slf4jVersion}</version> </dependency> + <!-- Others --> + <dependency> + <groupId>com.github.spullara.mustache.java</groupId> + <artifactId>compiler</artifactId> + <version>0.8.15</version> + </dependency> + <!-- Test --> <dependency> <groupId>org.mockito</groupId> -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
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 2e468378c44cc40fc6a92e80410ea1d79967f193 Merge: 9f52978 a6e1f56 Author: Yannick Martel <martel@©odelutin.com> Date: Fri Nov 21 11:31:49 2014 +0100 Merge branch 'feature/6012-create-user' into develop .gitignore | 3 +- .../src/main/xmi/coselmar-model.zargo | Bin 5234 -> 6024 bytes coselmar-rest/pom.xml | 59 ++++++ .../coselmar/beans/UserAccountCreatedMail.java | 81 +++++++ .../java/fr/ifremer/coselmar/beans/UserBean.java | 92 ++++++++ .../coselmar/converter/BeanEntityConverter.java | 13 ++ .../services/CoselmarRestApplicationListener.java | 4 +- .../coselmar/services/CoselmarServicesContext.java | 11 +- .../services/CoselmarWebServiceSupport.java | 1 + .../services/DefaultCoselmarServicesContext.java | 67 ++++++ .../services/config/CoselmarServicesConfig.java | 48 ++++- .../config/CoselmarServicesConfigOption.java | 41 +++- .../errors/InvalidCredentialException.java | 11 + .../coselmar/services/v1/UsersWebService.java | 232 +++++++++++++++++++++ .../resources/mail/UserAccountCreatedMail.mustache | 8 + .../mail/UserAccountCreatedMail_fr.mustache | 8 + coselmar-rest/src/main/resources/mapping | 11 +- .../services/AbstractCoselmarWebServiceTest.java | 92 ++++++++ .../services/FakeCoselmarApplicationContext.java | 224 ++++++++++++++++++++ .../services/FakeCoselmarServicesContext.java | 51 +++++ .../coselmar/services/UsersWebServiceTest.java | 59 ++++++ .../src/test/resources/coselmar-test.properties | 33 +++ coselmar-ui/src/main/webapp/index.html | 1 + .../src/main/webapp/js/coselmar-controllers.js | 72 ++++++- .../src/main/webapp/js/coselmar-services.js | 20 +- .../src/main/webapp/js/coselmar-user-services.js | 82 ++++++++ coselmar-ui/src/main/webapp/js/coselmar.js | 23 +- .../webapp/views/{ => documents}/document.html | 0 .../webapp/views/{ => documents}/documents.html | 0 .../webapp/views/{ => documents}/newdocument.html | 0 .../src/main/webapp/views/users/newuser.html | 79 +++++++ coselmar-ui/src/main/webapp/views/users/user.html | 26 +++ coselmar-ui/src/main/webapp/views/users/users.html | 41 ++++ pom.xml | 56 +++++ 34 files changed, 1507 insertions(+), 42 deletions(-) -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
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 984fbd9d0062e2a83dfea0a7ed23a3d841ed55de Merge: 2e46837 62e996a Author: Yannick Martel <martel@©odelutin.com> Date: Fri Nov 21 11:32:43 2014 +0100 Merge branch 'develop' of https://git.codelutin.com/coselmar into develop -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
participants (1)
-
codelutin.com scm