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 3ced62e2fbbf49af1cd68029b04c16e809082056 Author: Yannick Martel <martel@©odelutin.com> Date: Wed Feb 4 18:05:49 2015 +0100 manage authorized user on restricted document creation --- .../fr/ifremer/coselmar/beans/DocumentBean.java | 12 ++++++ .../coselmar/services/v1/DocumentsWebService.java | 48 +++++++++++++++++++--- .../src/main/webapp/js/coselmar-controllers.js | 35 +++++++++++++++- .../main/webapp/js/coselmar-questions-services.js | 2 - .../src/main/webapp/js/coselmar-services.js | 7 ++++ .../main/webapp/views/documents/newdocument.html | 16 ++++++++ 6 files changed, 112 insertions(+), 8 deletions(-) diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/DocumentBean.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/DocumentBean.java index 3b203e9..c58ba90 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/DocumentBean.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/beans/DocumentBean.java @@ -60,6 +60,9 @@ public class DocumentBean implements Serializable { protected Set<QuestionBean> relatedQuestions; protected int nbRelatedQuestions; + // If restricted, could have a list of restricted user + protected Set<UserBean> authorizedUsers; + public DocumentBean(String id, String name, String ownerName, String ownerId, String privacy, Date depositDate, Collection<String> keywords, String type, String summary, String language, Date publicationDate, @@ -94,6 +97,7 @@ public class DocumentBean implements Serializable { this.fileName = fileName; this.comment = comment; + this.authorizedUsers = new HashSet<>(0); } public String getId() { @@ -281,4 +285,12 @@ public class DocumentBean implements Serializable { public void setNbRelatedQuestions(int nbRelatedQuestions) { this.nbRelatedQuestions = nbRelatedQuestions; } + + public Set<UserBean> getAuthorizedUsers() { + return authorizedUsers; + } + + public void setAuthorizedUsers(Set<UserBean> authorizedUsers) { + this.authorizedUsers = authorizedUsers; + } } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/DocumentsWebService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/DocumentsWebService.java index 543a629..21e7379 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/DocumentsWebService.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/DocumentsWebService.java @@ -30,24 +30,28 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Set; import com.google.common.base.Function; import com.google.common.base.Preconditions; +import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import fr.ifremer.coselmar.beans.DocumentBean; import fr.ifremer.coselmar.beans.QuestionBean; +import fr.ifremer.coselmar.beans.UserBean; import fr.ifremer.coselmar.beans.UserWebToken; import fr.ifremer.coselmar.converter.BeanEntityConverter; +import fr.ifremer.coselmar.exceptions.CoselmarTechnicalException; import fr.ifremer.coselmar.persistence.entity.CoselmarUser; import fr.ifremer.coselmar.persistence.entity.CoselmarUserGroup; import fr.ifremer.coselmar.persistence.entity.CoselmarUserRole; import fr.ifremer.coselmar.persistence.entity.Document; import fr.ifremer.coselmar.persistence.entity.Privacy; import fr.ifremer.coselmar.persistence.entity.Question; -import fr.ifremer.coselmar.exceptions.CoselmarTechnicalException; import fr.ifremer.coselmar.services.CoselmarWebServiceSupport; import fr.ifremer.coselmar.services.errors.InvalidCredentialException; import fr.ifremer.coselmar.services.errors.NoResultException; @@ -75,7 +79,8 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { public static final List<String> DOCUMENT_CREATE_ALLOWED_USER_ROLES = Lists.newArrayList(CoselmarUserRole.ADMIN.name(), CoselmarUserRole.SUPERVISOR.name(), CoselmarUserRole.EXPERT.name()); - public static final List<String> DOCUMENT_EDIT_ALLOWED_USER_ROLES = + /** Kind of admin role **/ + public static final List<String> DOCUMENT_SUPER_USER_ROLES = Lists.newArrayList(CoselmarUserRole.ADMIN.name(), CoselmarUserRole.SUPERVISOR.name()); public static final List<String> DOCUMENT_VIEW_ALLOWED_USER_ROLES = @@ -228,7 +233,22 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { documentEntity.setOwner(owner); documentEntity.setName(documentName); - documentEntity.setPrivacy(Privacy.valueOf(document.getPrivacy().toUpperCase())); + + String privacy = document.getPrivacy().toUpperCase(); + documentEntity.setPrivacy(Privacy.valueOf(privacy)); + + // Manage privacy : if restricted, create an UserGroup with authorized users + if (StringUtils.equals(Privacy.RESTRICTED.name(), privacy)) { + Set<UserBean> authorizedUsers = document.getAuthorizedUsers(); + Set<CoselmarUser> coselmarUsers = retrieveUsers(authorizedUsers); + CoselmarUserGroup restrictedUsers = getCoselmarUserGroupDao().create(); + restrictedUsers.setName(documentEntity.getTopiaId()); + + restrictedUsers.addAllMembers(coselmarUsers); + documentEntity.addRestrictedList(restrictedUsers); + + } + documentEntity.addAllKeywords(document.getKeywords()); Date depositDate = document.getDepositDate(); @@ -295,7 +315,7 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { Document document = getDocumentDao().forTopiaIdEquals(documentFullId).findAny(); // Only Owner Expert or Supervisor/Admin can add document file - if (!DOCUMENT_EDIT_ALLOWED_USER_ROLES.contains(currentUser.getRole().name()) + if (!DOCUMENT_SUPER_USER_ROLES.contains(currentUser.getRole().name()) && document.getOwner() != currentUser) { String message = String.format("User %s %s ('%s') is not allowed to add document file", currentUser.getFirstname(), currentUser.getName(), getShortIdFromFull(currentUser.getTopiaId())); @@ -448,7 +468,7 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { Document document = getDocumentDao().forTopiaIdEquals(fullId).findUnique(); - if (!DOCUMENT_EDIT_ALLOWED_USER_ROLES.contains(currentUser.getRole().name()) + if (!DOCUMENT_SUPER_USER_ROLES.contains(currentUser.getRole().name()) && document.getOwner() != currentUser) { String message = String.format("User %s %s ('%s') try to delete document '%s'", @@ -563,6 +583,10 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { String viewerRole = user.getRole().name().toUpperCase(); + if (DOCUMENT_SUPER_USER_ROLES.contains(viewerRole) || document.getOwner() == user) { + return true; + } + // For public : only admin/supervisor/expert can access if (document.getPrivacy() == Privacy.PUBLIC) { isAuthorized = DOCUMENT_VIEW_ALLOWED_USER_ROLES.contains(viewerRole); @@ -617,4 +641,18 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { document.setWithFile(false); } } + + protected Set<CoselmarUser> retrieveUsers(Collection<UserBean> userBeans) { + Function<UserBean, String> getIds = new Function<UserBean, String>() { + @Override + public String apply(UserBean userBean) { + return getFullIdFromShort(CoselmarUser.class, userBean.getId()); + } + }; + + Collection<String> userIds = Collections2.transform(userBeans, getIds); + List<CoselmarUser> coselmarUsers = getCoselmarUserDao().forTopiaIdIn(userIds).findAll(); + return new HashSet<>(coselmarUsers); + + } } diff --git a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js index 86e2cf7..75dad07 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js @@ -139,14 +139,47 @@ coselmarControllers.controller("DocumentsCtrl", ['$scope', '$route', '$routePara // Controller for new document View coselmarControllers.controller("NewDocumentCtrl", ['$scope', '$location', 'documentService', function($scope, $location, documentService){ - $scope.document = {'type' : 'PERIODICAL_PUBLICATION', 'privacy': 'PUBLIC', 'keywords': []}; + $scope.document = {'type' : 'PERIODICAL_PUBLICATION', 'privacy': 'PUBLIC', 'keywords': [], 'authorizedUsers' : []}; $scope.upload = {}; $scope.existing = {'types' : [], 'keywords' : []}; + $scope.users = []; + + console.log("prout"); documentService.findAllTypes(function(results) { $scope.existing.types = results; }); + // Participants, clients and supervisors management for ui-select + $scope.usersIndex = []; + $scope.refreshUsers = function(searchKeyword) { + var searchKeywords = []; + if (searchKeyword && searchKeyword.length > 0) { + searchKeywords.push(searchKeyword); + } + + documentService.findUsers({'role': 'EXPERT', 'active': true, 'fullTextSearch' : searchKeywords}, function(users) { + $scope.users = users; + $scope.usersIndex = []; + angular.forEach($scope.users, function(user) { + $scope.usersIndex[user.id] = user; + }); + bindUsers($scope.document.authorizedUsers, $scope.usersIndex); + }); + } + + // function to be sure to have same user objects in list + var bindUsers = function(toDeal, index) { + if (toDeal) { + for(var i = 0; i < toDeal.length; i++) { + var user = toDeal[i]; + if (index[user.id]) { + toDeal[i] = index[user.id]; + } + } + } + }; + documentService.findAllKeywords(function(results) { $scope.existing.keywords = results; }); diff --git a/coselmar-ui/src/main/webapp/js/coselmar-questions-services.js b/coselmar-ui/src/main/webapp/js/coselmar-questions-services.js index f5f4d1e..3c0cac6 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-questions-services.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-questions-services.js @@ -85,8 +85,6 @@ function Question(resource, config){ this.addNewDocuments = function(questionId, documents, successFunction, failFunction) { - var formData = new FormData(); - formData.append("documents", JSON.stringify(documents)); var documentsParam = $.param({'documents': JSON.stringify(documents)}) var serviceURl = baseURL + "/" + questionId + "/documents"; diff --git a/coselmar-ui/src/main/webapp/js/coselmar-services.js b/coselmar-ui/src/main/webapp/js/coselmar-services.js index 76cadac..6e2f2f7 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-services.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-services.js @@ -32,6 +32,7 @@ function Document(resource, config){ this.resource = resource; var baseURL = config.BASE_URL + "/documents"; + var usersURL = config.BASE_URL + "/users"; this.saveDocument = function(document, successFunction, failFunction) { @@ -129,4 +130,10 @@ function Document(resource, config){ docResource.query(successFunction); }; + this.findUsers = function(example, successFunction) { + var userResource = resource(usersURL, {'search': example}); + userResource.query(successFunction); + + }; + }; \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/views/documents/newdocument.html b/coselmar-ui/src/main/webapp/views/documents/newdocument.html index e73cd89..e4d73c3 100644 --- a/coselmar-ui/src/main/webapp/views/documents/newdocument.html +++ b/coselmar-ui/src/main/webapp/views/documents/newdocument.html @@ -113,6 +113,22 @@ <div ng-if="document.privacy == 'RESTRICTED'"> {{ 'common.message.notYetAvailable' | translate }} + + <ui-select multiple ng-model="document.authorizedUsers" + theme="bootstrap" reset-search-input="true" + ng-disabled="disabled" class="form-control"> + + <ui-select-match placeholder="John Doe"> + {{$item.firstName}} {{$item.name}} ({{$item.organization}}) + </ui-select-match> + + <ui-select-choices + repeat="user in users track by user.id | propsFilter: {name: $select.search, firstName: $select.search, organization: $select.search}" + refresh="refreshUsers($select.search)" + refresh-delay="500"> + {{user.firstName}} {{user.name}} ({{user.organization}}) + </ui-select-choices> + </ui-select> </div> </div> </div> -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.