branch develop updated (43e514c -> 2ae6ffa)
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 43e514c Refs #6577 : Syntaxical modification new ed571a6 prepare service : user is authorized to see a restricted document he is in list new db2e7e2 add restricted document in documents list (update database request) new 621be68 fix case of remove related and closing 'restricted' documents and impact on document access new 658e66c just be sure participant group name is same as question title new 3ced62e manage authorized user on restricted document creation new 7e1d69d manage authorized users in document get, and begin update mangement new 4d74950 can modify privacy and authorized user in document edit new 8071f46 add API to get experts list, available for expert users new 0667fa1 Merge branch 'develop' into feature/6515-restrected-access-on-document new 2ae6ffa Fixes #6515 Merge branch 'feature/6515-restrected-access-on-document' into develop The 10 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 2ae6ffac13d650ca6af0bcb2fadd7babb1102a83 Merge: 43e514c 0667fa1 Author: Yannick Martel <martel@©odelutin.com> Date: Thu Feb 5 11:38:55 2015 +0100 Fixes #6515 Merge branch 'feature/6515-restrected-access-on-document' into develop commit 0667fa1f1cd2db32d3ec82c03deb94e478cf911b Merge: 8071f46 43e514c Author: Yannick Martel <martel@©odelutin.com> Date: Thu Feb 5 11:38:19 2015 +0100 Merge branch 'develop' into feature/6515-restrected-access-on-document commit 8071f4691e7c46a0f5cc98cda8df7e2c10494f71 Author: Yannick Martel <martel@©odelutin.com> Date: Thu Feb 5 11:37:29 2015 +0100 add API to get experts list, available for expert users commit 4d74950953e7657ea39edafb90e0ff8f7d178ccd Author: Yannick Martel <martel@©odelutin.com> Date: Thu Feb 5 10:44:34 2015 +0100 can modify privacy and authorized user in document edit commit 7e1d69de67769abfd815cfe82abaf6a45dc2368b Author: Yannick Martel <martel@©odelutin.com> Date: Wed Feb 4 19:48:47 2015 +0100 manage authorized users in document get, and begin update mangement commit 3ced62e2fbbf49af1cd68029b04c16e809082056 Author: Yannick Martel <martel@©odelutin.com> Date: Wed Feb 4 18:05:49 2015 +0100 manage authorized user on restricted document creation commit 658e66cc97a9514a715b9c23b12dfb8e33f7df9a Author: Yannick Martel <martel@©odelutin.com> Date: Wed Feb 4 15:52:38 2015 +0100 just be sure participant group name is same as question title commit 621be68a7527c4bd490926a33e83e8506bb342ae Author: Yannick Martel <martel@©odelutin.com> Date: Wed Feb 4 15:34:25 2015 +0100 fix case of remove related and closing 'restricted' documents and impact on document access commit db2e7e2f3bd84df459d6f92676151777457ba2e7 Author: Yannick Martel <martel@©odelutin.com> Date: Wed Feb 4 11:22:40 2015 +0100 add restricted document in documents list (update database request) commit ed571a6f9dbc7e14d48722362706cd25209ac28c Author: Yannick Martel <martel@©odelutin.com> Date: Tue Feb 3 18:23:47 2015 +0100 prepare service : user is authorized to see a restricted document he is in list Summary of changes: .../persistence/entity/DocumentTopiaDao.java | 13 +- .../fr/ifremer/coselmar/beans/DocumentBean.java | 19 ++ .../services/CoselmarWebServiceSupport.java | 77 ++++++++- .../coselmar/services/v1/DocumentsWebService.java | 192 ++++++++++++++++----- .../coselmar/services/v1/QuestionsWebService.java | 83 +++++++-- .../coselmar/services/v1/UsersWebService.java | 46 +++++ coselmar-rest/src/main/resources/mapping | 1 + coselmar-ui/src/main/webapp/i18n/en.js | 1 + coselmar-ui/src/main/webapp/i18n/fr.js | 1 + .../src/main/webapp/js/coselmar-controllers.js | 71 +++++++- .../main/webapp/js/coselmar-questions-services.js | 2 - .../src/main/webapp/js/coselmar-services.js | 7 + .../main/webapp/views/documents/editDocument.html | 28 ++- .../main/webapp/views/documents/newdocument.html | 18 +- 14 files changed, 484 insertions(+), 75 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 ed571a6f9dbc7e14d48722362706cd25209ac28c Author: Yannick Martel <martel@©odelutin.com> Date: Tue Feb 3 18:23:47 2015 +0100 prepare service : user is authorized to see a restricted document he is in list --- .../services/CoselmarWebServiceSupport.java | 77 +++++++++++++++++++- .../coselmar/services/v1/DocumentsWebService.java | 85 +++++++++++----------- 2 files changed, 118 insertions(+), 44 deletions(-) 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 373853b..e634047 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 @@ -34,6 +34,7 @@ import java.util.Map; import com.auth0.jwt.JWTVerifier; import fr.ifremer.coselmar.beans.UserWebToken; +import fr.ifremer.coselmar.config.CoselmarServicesConfig; import fr.ifremer.coselmar.exceptions.CoselmarTechnicalException; import fr.ifremer.coselmar.persistence.CoselmarPersistenceContext; import fr.ifremer.coselmar.persistence.entity.CoselmarUser; @@ -41,7 +42,6 @@ import fr.ifremer.coselmar.persistence.entity.CoselmarUserGroupTopiaDao; import fr.ifremer.coselmar.persistence.entity.CoselmarUserTopiaDao; import fr.ifremer.coselmar.persistence.entity.DocumentTopiaDao; import fr.ifremer.coselmar.persistence.entity.QuestionTopiaDao; -import fr.ifremer.coselmar.config.CoselmarServicesConfig; import fr.ifremer.coselmar.services.errors.InvalidCredentialException; import fr.ifremer.coselmar.services.v1.DocumentsWebService; import org.apache.commons.codec.binary.Base64; @@ -50,6 +50,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.debux.webmotion.server.WebMotionController; import org.debux.webmotion.server.call.HttpContext; +import org.nuiton.topia.persistence.TopiaNoResultException; /** * @author ymartel <martel@codelutin.com> @@ -132,6 +133,18 @@ public abstract class CoselmarWebServiceSupport extends WebMotionController impl getPersistenceContext().rollback(); } + /** + * Check the authorization code. + * Get the token from the authorization and reconstitute JWT user token. + * + * @param authorization : authorization containing the encoding token + * @return corresponding {@link fr.ifremer.coselmar.beans.UserWebToken} + * + * @throws InvalidCredentialException if token is not valid. + * + * @Deprecated since 0.8 : prefer use {@link #checkUserAuthentication(String)} that also check user validity. + */ + @Deprecated protected UserWebToken checkAuthentication(String authorization) throws InvalidCredentialException { try { @@ -161,6 +174,57 @@ public abstract class CoselmarWebServiceSupport extends WebMotionController impl } /** + * Check the authorization code. + * Get the token from the authorization and reconstitute JWT user token. + * From this token, retrieve the user from database. + * + * @param authorization : authorization containing the encoding token + * + * @return corresponding {@link fr.ifremer.coselmar.persistence.entity.CoselmarUser} + * + * @throws InvalidCredentialException if token is not valid or if user does not exist. + */ + protected CoselmarUser checkUserAuthentication(String authorization) throws InvalidCredentialException { + try { + + String webSecurityKey = getServicesContext().getCoselmarServicesConfig().getWebSecurityKey(); + JWTVerifier jwtVerifier = new JWTVerifier(Base64.encodeBase64String(webSecurityKey.getBytes("utf8")), "audience"); + + String token = StringUtils.replace(authorization, "Bearer ", ""); + Map<String, Object> claims = jwtVerifier.verify(token); + UserWebToken userWebToken = new UserWebToken(claims); + + // check user still exist + String userId = getFullUserIdFromShort(userWebToken.getUserId()); + CoselmarUser coselmarUser = getCoselmarUserDao().forTopiaIdEquals(userId).findAny(); + + return coselmarUser; + + } catch (NoSuchAlgorithmException|InvalidKeyException|IOException e) { + // This should not happened or this is really exceptional ! + if (log.isErrorEnabled()) { + log.error("Error during JWT verification : wrong Algorithm !", e); + } + throw new CoselmarTechnicalException(e); + + } catch (SignatureException e) { + // Invalid Signature ! It's a Fake ! + if (log.isErrorEnabled()) { + log.error("Error during JWT verification : bad signature!", e); + } + throw new InvalidCredentialException("Error with signature"); + + } catch (TopiaNoResultException e) { + // User not found, maybe old token ? Or well faked ! + if (log.isErrorEnabled()) { + log.error("Error during authorization check : user does not exist !", e); + } + throw new InvalidCredentialException("User not known"); + } + + } + + /** * Construct the full id of an user from the random part contained in * {@link fr.ifremer.coselmar.beans.UserWebToken}. * @@ -183,4 +247,15 @@ public abstract class CoselmarWebServiceSupport extends WebMotionController impl protected String getFullIdFromShort(Class clazz, String shortId) { return clazz.getCanonicalName() + getPersistenceContext().getTopiaIdFactory().getSeparator() + shortId; } + + /** + * Construct a light id with only the random part. + * + * @param fullId : the full id from which extract the random part + * + * @return a light id. + */ + protected String getShortIdFromFull(String fullId) { + return getPersistenceContext().getTopiaIdFactory().getRandomPart(fullId); + } } 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 faf3a41..543a629 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 @@ -32,6 +32,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Set; import com.google.common.base.Function; import com.google.common.base.Preconditions; @@ -41,6 +42,7 @@ import fr.ifremer.coselmar.beans.QuestionBean; import fr.ifremer.coselmar.beans.UserWebToken; import fr.ifremer.coselmar.converter.BeanEntityConverter; 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; @@ -70,8 +72,11 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { private static final Log log = getLog(DocumentsWebService.class); + 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 = - Lists.newArrayList(CoselmarUserRole.ADMIN.name(), CoselmarUserRole.EXPERT.name(), CoselmarUserRole.SUPERVISOR.name()); + Lists.newArrayList(CoselmarUserRole.ADMIN.name(), CoselmarUserRole.SUPERVISOR.name()); public static final List<String> DOCUMENT_VIEW_ALLOWED_USER_ROLES = Lists.newArrayList( @@ -84,7 +89,7 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { // Check authentication String authorization = getContext().getHeader("Authorization"); - UserWebToken userWebToken = checkAuthentication(authorization); + CoselmarUser currentUser = checkUserAuthentication(authorization); // reconstitute full id String fullId = getDocumentFullId(documentId); @@ -93,10 +98,10 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { // If document if public, only admin, supervisor and expert could view it // If document if private, only admin, supervisor and owner could view it - if (!isAllowedToAccessDocument(userWebToken, document)) { + if (!isAllowedToAccessDocument(currentUser, document)) { String message = String.format("User %s %s ('%s') try to access to document '%s'", - userWebToken.getFirstName(), userWebToken.getLastName(), userWebToken.getUserId(), documentId); + currentUser.getFirstname(), currentUser.getName(), getShortIdFromFull(currentUser.getTopiaId()), documentId); if (log.isWarnEnabled()) { log.warn(message); } @@ -180,7 +185,7 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { // Only Expert or Supervisor can add document String userRole = userWebToken.getRole(); - if (!DOCUMENT_EDIT_ALLOWED_USER_ROLES.contains(userRole.toUpperCase())) { + if (!DOCUMENT_CREATE_ALLOWED_USER_ROLES.contains(userRole.toUpperCase())) { String message = String.format("User %s %s ('%s') is not allowed to add document", userWebToken.getFirstName(), userWebToken.getLastName(), userWebToken.getUserId()); if (log.isWarnEnabled()) { @@ -278,41 +283,28 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { public void addDocumentFile(String documentId, UploadFile uploadFile) throws InvalidCredentialException, UnauthorizedException { + + Preconditions.checkNotNull(documentId); + Preconditions.checkNotNull(uploadFile); + // Check authentication String authorization = getContext().getHeader("Authorization"); - UserWebToken userWebToken = checkAuthentication(authorization); + CoselmarUser currentUser = checkUserAuthentication(authorization); - // Only Expert or Supervisor can add document - String userRole = userWebToken.getRole(); - if (!DOCUMENT_EDIT_ALLOWED_USER_ROLES.contains(userRole.toUpperCase())) { - String message = String.format("User %s %s ('%s') is not allowed to add document", - userWebToken.getFirstName(), userWebToken.getLastName(), userWebToken.getUserId()); + String documentFullId = getFullIdFromShort(Document.class, documentId); + 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()) + && 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())); if (log.isWarnEnabled()) { log.warn(message); } throw new UnauthorizedException(message); } - Preconditions.checkNotNull(documentId); - Preconditions.checkNotNull(uploadFile); - - // retrieve current user to check identity - String userFullId = getFullUserIdFromShort(userWebToken.getUserId()); - - try { - getCoselmarUserDao().forTopiaIdEquals(userFullId).findUnique(); - } catch (TopiaNoResultException tnre) { - // Should not happened, cause user are not really deleted - String message = String.format("Seems that logged user ('%s') does not exist anymore.", userFullId); - if (log.isErrorEnabled()) { - log.error(message); - } - throw new InvalidCredentialException(message); - } - - String documentFullId = getFullIdFromShort(Document.class, documentId); - Document document = getDocumentDao().forTopiaIdEquals(documentFullId).findAny(); - // Get owner to place correctly the file CoselmarUser owner = document.getOwner(); Pair<String, String> pathAndContentType = managerDocumentFile(uploadFile, owner); @@ -372,16 +364,16 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { // Check authentication String authorization = getContext().getHeader("Authorization"); - UserWebToken userWebToken = checkAuthentication(authorization); + CoselmarUser currentUser = checkUserAuthentication(authorization); String documentId = getDocumentFullId(document.getId()); Document documentEntity = getDocumentDao().forTopiaIdEquals(documentId).findUnique(); - if (!isAllowedToAccessDocument(userWebToken, documentEntity)) { + if (!isAllowedToAccessDocument(currentUser, documentEntity)) { String message = String.format("User %s %s ('%s') try to modify document '%s'", - userWebToken.getFirstName(), userWebToken.getLastName(), userWebToken.getUserId(), documentId); + currentUser.getFirstname(), currentUser.getName(), getShortIdFromFull(currentUser.getTopiaId()), documentId); if (log.isWarnEnabled()) { log.warn(message); } @@ -449,17 +441,18 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { // Check authentication String authorization = getContext().getHeader("Authorization"); - UserWebToken userWebToken = checkAuthentication(authorization); + CoselmarUser currentUser = checkUserAuthentication(authorization); // reconstitute full id String fullId = getDocumentFullId(documentId); Document document = getDocumentDao().forTopiaIdEquals(fullId).findUnique(); - if (!isAllowedToAccessDocument(userWebToken, document)) { + if (!DOCUMENT_EDIT_ALLOWED_USER_ROLES.contains(currentUser.getRole().name()) + && document.getOwner() != currentUser) { String message = String.format("User %s %s ('%s') try to delete document '%s'", - userWebToken.getFirstName(), userWebToken.getLastName(), userWebToken.getUserId(), documentId); + currentUser.getFirstname(), currentUser.getName(), getShortIdFromFull(currentUser.getTopiaId()), documentId); if (log.isWarnEnabled()) { log.warn(message); } @@ -559,16 +552,16 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { * Check if an user can access to a document metadata, according to its * privacy settings and the user grant. * - * @param userWebToken : Session data for current user, + * @param user : Current User, * containing {@link fr.ifremer.coselmar.persistence.entity.CoselmarUserRole} as String * @param document : the document user trying to access. * * @return true is user can access, false else. */ - protected boolean isAllowedToAccessDocument(UserWebToken userWebToken, Document document) { + protected boolean isAllowedToAccessDocument(CoselmarUser user, Document document) { boolean isAuthorized = false; - String viewerRole = userWebToken.getRole().toUpperCase(); + String viewerRole = user.getRole().name().toUpperCase(); // For public : only admin/supervisor/expert can access if (document.getPrivacy() == Privacy.PUBLIC) { @@ -577,11 +570,17 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { // For Private : only admin/supervisor/owner can access } else if (document.getPrivacy() == Privacy.PRIVATE) { CoselmarUser documentOwner = document.getOwner(); - boolean isOwner = StringUtils.equals(documentOwner.getTopiaId(), getFullUserIdFromShort(userWebToken.getUserId())); + boolean isOwner = StringUtils.equals(documentOwner.getTopiaId(), user.getTopiaId()); isAuthorized = isOwner || Lists.newArrayList(CoselmarUserRole.ADMIN.name(), CoselmarUserRole.SUPERVISOR.name()).contains(viewerRole); - } else { - // Restricted : Not yet implemented + } else if (document.getPrivacy() == Privacy.RESTRICTED) { + Set<CoselmarUserGroup> restrictedLists = document.getRestrictedList(); + for (CoselmarUserGroup restrictedList : restrictedLists) { + if (restrictedList.containsMembers(user)) { + isAuthorized = true; + break; + } + } } return isAuthorized; -- 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 db2e7e2f3bd84df459d6f92676151777457ba2e7 Author: Yannick Martel <martel@©odelutin.com> Date: Wed Feb 4 11:22:40 2015 +0100 add restricted document in documents list (update database request) --- .../coselmar/persistence/entity/DocumentTopiaDao.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/DocumentTopiaDao.java b/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/DocumentTopiaDao.java index 7bd5fc8..acbcd41 100644 --- a/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/DocumentTopiaDao.java +++ b/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/DocumentTopiaDao.java @@ -59,7 +59,8 @@ public class DocumentTopiaDao extends AbstractDocumentTopiaDao<Document> { public List<Document> findAllFilterByUser(CoselmarUser currentUser, List<String> keywords) { - StringBuilder hqlBuilder = new StringBuilder("FROM " + Document.class.getName() + " D"); + StringBuilder hqlBuilder = new StringBuilder("SELECT D FROM " + Document.class.getName() + " D" + + " LEFT OUTER JOIN D." + Document.PROPERTY_RESTRICTED_LIST + " CUG "); Map<String, Object> args = new HashMap<>(); @@ -67,11 +68,13 @@ public class DocumentTopiaDao extends AbstractDocumentTopiaDao<Document> { String privacyPublicCondition = DaoUtils.getQueryForAttributeEquals("D", Document.PROPERTY_PRIVACY, args, Privacy.PUBLIC, ""); hqlBuilder.append(" WHERE ( " + privacyPublicCondition); - // Can list his own private document - String privacyPrivateCondition = DaoUtils.getQueryForAttributeEquals("D", Document.PROPERTY_PRIVACY, args, Privacy.PRIVATE, ""); - String ownerCondition = DaoUtils.andAttributeEquals("D", Document.PROPERTY_OWNER, args, currentUser); + // Can list his own document + String ownerCondition = DaoUtils.orAttributeEquals("D", Document.PROPERTY_OWNER, args, currentUser); + hqlBuilder.append(ownerCondition); - hqlBuilder.append(" OR ( " + privacyPrivateCondition + " " + ownerCondition + " ) )"); + // For limited access, check if user is in a restricted list + String participantCondition = DaoUtils.orAttributeContains("CUG", CoselmarUserGroup.PROPERTY_MEMBERS, args, currentUser); + hqlBuilder.append(participantCondition + ")"); // Manage keywords search in : title, summary, authors and keywords -- 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 621be68a7527c4bd490926a33e83e8506bb342ae Author: Yannick Martel <martel@©odelutin.com> Date: Wed Feb 4 15:34:25 2015 +0100 fix case of remove related and closing 'restricted' documents and impact on document access --- .../coselmar/services/v1/QuestionsWebService.java | 82 +++++++++++++++++----- 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java index 9e3bdcc..49ab602 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java @@ -133,7 +133,7 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { questionEntity.setPrivacy(realPrivacy); // On creation, Status is Open - questionEntity.setStatus(Status.OPEN); + questionEntity.setStatus(Status.IN_PROGRESS); // Manage Dates : submission & deadline Date submissionDate = question.getSubmissionDate(); @@ -573,6 +573,9 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { // it could be a reopen ... } else if (questionEntity.getClosingDate() != null && !Lists.newArrayList(Status.CLOSED.name(), Status.ADJOURNED.name()).contains(status)) { questionEntity.setClosingDate(null); + // XXX ymartel 2015/02/04 : Should we do ? +// questionEntity.setConclusion(null); +// questionEntity.clearClosingDocuments(); } } else { @@ -669,40 +672,87 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { } - // Documents on init + // Manage Documents list Set<DocumentBean> relatedDocuments = question.getRelatedDocuments(); + Set<Document> documents = null; + + if (relatedDocuments != null && !relatedDocuments.isEmpty()) { + documents = retrieveDocuments(relatedDocuments); + } + + // In edition : make a diff, remove restricted list for removed documents, clear documents + if (inEdition) { + Set<Document> presentDocuments = questionEntity.getRelatedDocuments(); + + if (documents == null) { + for (Document presentDocument : presentDocuments) { + if (presentDocument.getPrivacy() == Privacy.RESTRICTED) { + presentDocument.removeRestrictedList(participantGroup); + } + } + questionEntity.clearRelatedDocuments(); + } else { + for (Document presentDocument : presentDocuments) { + if (!documents.contains(presentDocument) && presentDocument.getPrivacy() == Privacy.RESTRICTED) { + presentDocument.removeRestrictedList(participantGroup); + } + } + questionEntity.clearRelatedDocuments(); + } + } + if (relatedDocuments != null && !relatedDocuments.isEmpty()) { - Set<Document> documents = retrieveDocuments(relatedDocuments); // Manage restriction list for document with Privacy.RESTRICTED for (Document document : documents) { if (document.getPrivacy() == Privacy.RESTRICTED) { document.addRestrictedList(participantGroup); } } - - questionEntity.clearRelatedDocuments(); questionEntity.addAllRelatedDocuments(documents); - } else if (inEdition) { - questionEntity.clearRelatedDocuments(); } + questionEntity.setConclusion(question.getConclusion()); - // Documents on init - Set<DocumentBean> closingDocuments = question.getClosingDocuments(); - if (closingDocuments != null && !closingDocuments.isEmpty()) { - Set<Document> documents = retrieveDocuments(closingDocuments); + // Closing documents : here we re-go + Set<DocumentBean> closingDocumentBeans = question.getClosingDocuments(); + + Set<Document> closingDocuments = null; + if (closingDocumentBeans != null && !closingDocumentBeans.isEmpty()) { + closingDocuments = retrieveDocuments(closingDocumentBeans); + } + + // In edition : make a diff, remove restricted list for removed closing documents, clear closing documents + if (inEdition) { + Set<Document> presentClosingDocuments = questionEntity.getClosingDocuments(); + + if (closingDocuments == null) { + for (Document presentClosingDocument : presentClosingDocuments) { + if (presentClosingDocument.getPrivacy() == Privacy.RESTRICTED) { + presentClosingDocument.removeRestrictedList(participantGroup); + } + } + questionEntity.clearClosingDocuments(); + + } else { + for (Document presentClosingDocument : presentClosingDocuments) { + if (!closingDocuments.contains(presentClosingDocument) && presentClosingDocument.getPrivacy() == Privacy.RESTRICTED) { + presentClosingDocument.removeRestrictedList(participantGroup); + } + } + questionEntity.clearClosingDocuments(); + } + } + + if (closingDocuments != null) { // Manage restriction list for document with Privacy.RESTRICTED - for (Document document : documents) { + for (Document document : closingDocuments) { if (document.getPrivacy() == Privacy.RESTRICTED) { document.addRestrictedList(participantGroup); } } - questionEntity.clearClosingDocuments(); - questionEntity.addAllClosingDocuments(documents); - } else if (inEdition) { - questionEntity.clearClosingDocuments(); + questionEntity.addAllClosingDocuments(closingDocuments); } 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 658e66cc97a9514a715b9c23b12dfb8e33f7df9a Author: Yannick Martel <martel@©odelutin.com> Date: Wed Feb 4 15:52:38 2015 +0100 just be sure participant group name is same as question title --- .../main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java index 49ab602..f32c983 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java @@ -619,6 +619,7 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { //On update, get the existing group, make a diff : removed participants become contributor if (inEdition) { participantGroup = questionEntity.getParticipants(); + participantGroup.setName(question.getTitle()); if (participants != null && !participants.isEmpty()) { Set<CoselmarUser> expertEntities = retrieveUsers(participants); -- 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 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>.
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 7e1d69de67769abfd815cfe82abaf6a45dc2368b Author: Yannick Martel <martel@©odelutin.com> Date: Wed Feb 4 19:48:47 2015 +0100 manage authorized users in document get, and begin update mangement --- .../fr/ifremer/coselmar/beans/DocumentBean.java | 7 +++ .../coselmar/services/v1/DocumentsWebService.java | 63 +++++++++++++++++++++- .../main/webapp/views/documents/newdocument.html | 2 +- 3 files changed, 70 insertions(+), 2 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 c58ba90..c7527c6 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 @@ -293,4 +293,11 @@ public class DocumentBean implements Serializable { public void setAuthorizedUsers(Set<UserBean> authorizedUsers) { this.authorizedUsers = authorizedUsers; } + + public void addAuthorizedUser(UserBean userBean) { + if (this.authorizedUsers == null) { + this.authorizedUsers = new HashSet<>(); + } + this.authorizedUsers.add(userBean); + } } 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 21e7379..b7aab6e 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 @@ -123,6 +123,22 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { documentBean.addRelatedQuestion(questionBean); } + // Manage restricted access + if (document.getPrivacy() == Privacy.RESTRICTED) { + Set<CoselmarUserGroup> restrictedList = document.getRestrictedList(); + for (CoselmarUserGroup usersGroup : restrictedList) { + if (StringUtils.equalsIgnoreCase(fullId, usersGroup.getName())) { + Set<CoselmarUser> members = usersGroup.getMembers(); + for (CoselmarUser member : members) { + String userLightId = getPersistenceContext().getTopiaIdFactory().getRandomPart(member.getTopiaId()); + UserBean userBean = BeanEntityConverter.toBean(userLightId, member); + documentBean.addAuthorizedUser(userBean); + } + } + } + } + + return documentBean; } @@ -411,7 +427,52 @@ public class DocumentsWebService extends CoselmarWebServiceSupport { } documentEntity.setName(document.getName()); - documentEntity.setPrivacy(Privacy.valueOf(document.getPrivacy().toUpperCase())); + String oldPrivacy = documentEntity.getPrivacy().name(); + String newPrivacy = document.getPrivacy().toUpperCase(); + documentEntity.setPrivacy(Privacy.valueOf(newPrivacy)); + + // Manage privacy : if restricted, create an UserGroup with authorized users + if (StringUtils.equals(Privacy.RESTRICTED.name(), newPrivacy)) { + Set<UserBean> authorizedUsers = document.getAuthorizedUsers(); + Set<CoselmarUser> coselmarUsers = retrieveUsers(authorizedUsers); + + Set<CoselmarUserGroup> restrictedList = documentEntity.getRestrictedList(); + CoselmarUserGroup restrictedUsers = null; + if (restrictedList != null && !restrictedList.isEmpty()) { + + // Try to retrieve the UserGroup with documentId as name (corresponding to user choice) + for (CoselmarUserGroup usersList : restrictedList) { + if (StringUtils.equalsIgnoreCase(documentId, usersList.getName())) { + restrictedUsers = usersList; + restrictedUsers.clearMembers(); + break; + } + } + } + if (restrictedUsers == null) { + restrictedUsers = getCoselmarUserGroupDao().create(); + restrictedUsers.setName(documentEntity.getTopiaId()); + } + + restrictedUsers.addAllMembers(coselmarUsers); + documentEntity.addRestrictedList(restrictedUsers); + + } else if (StringUtils.equals(Privacy.RESTRICTED.name(), oldPrivacy)) { + // retrieve restrictive users list and remove it + CoselmarUserGroup restrictedUsers = null; + for (CoselmarUserGroup usersList : documentEntity.getRestrictedList()) { + if (StringUtils.equalsIgnoreCase(documentId, usersList.getName())) { + restrictedUsers = usersList; + break; + } + } + + // Remove group from document, and delete it ! + if (restrictedUsers != null) { + documentEntity.removeRestrictedList(restrictedUsers); + getCoselmarUserGroupDao().delete(restrictedUsers); + } + } documentEntity.clearKeywords(); documentEntity.addAllKeywords(document.getKeywords()); diff --git a/coselmar-ui/src/main/webapp/views/documents/newdocument.html b/coselmar-ui/src/main/webapp/views/documents/newdocument.html index e4d73c3..96da0c7 100644 --- a/coselmar-ui/src/main/webapp/views/documents/newdocument.html +++ b/coselmar-ui/src/main/webapp/views/documents/newdocument.html @@ -112,7 +112,7 @@ </select> <div ng-if="document.privacy == 'RESTRICTED'"> - {{ 'common.message.notYetAvailable' | translate }} + {{ 'document.metadata.restricted.info' | translate }} <ui-select multiple ng-model="document.authorizedUsers" theme="bootstrap" reset-search-input="true" -- 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 4d74950953e7657ea39edafb90e0ff8f7d178ccd Author: Yannick Martel <martel@©odelutin.com> Date: Thu Feb 5 10:44:34 2015 +0100 can modify privacy and authorized user in document edit --- .../src/main/webapp/js/coselmar-controllers.js | 36 ++++++++++++++++++++++ .../main/webapp/views/documents/editDocument.html | 28 +++++++++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js index 75dad07..8c23c11 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js @@ -232,6 +232,7 @@ coselmarControllers.controller("DocumentViewCtrl", $scope.container = {baseUrl : coselmarConfig.BASE_URL}; $scope.upload = {}; + $scope.users = []; $scope.editSession = $routeParams.edit ? $routeParams.edit : false; @@ -242,6 +243,11 @@ coselmarControllers.controller("DocumentViewCtrl", if (document.publicationDate) { $scope.document.publicationDate = new Date(document.publicationDate); } + // update scope about current user : if he is participant, more option enable in ui + if (document.authorizedUsers) { + $scope.users = document.authorizedUsers; + bindUsers($scope.document.authorizedUsers, $scope.usersIndex); + } }); $scope.deleteDocument = function(documentId){ @@ -335,6 +341,36 @@ coselmarControllers.controller("DocumentViewCtrl", } }; + // 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]; + } + } + } + }; + } ]); diff --git a/coselmar-ui/src/main/webapp/views/documents/editDocument.html b/coselmar-ui/src/main/webapp/views/documents/editDocument.html index 4d538e3..7764bc8 100644 --- a/coselmar-ui/src/main/webapp/views/documents/editDocument.html +++ b/coselmar-ui/src/main/webapp/views/documents/editDocument.html @@ -95,8 +95,32 @@ <label class="col-md-2 control-label">{{ 'document.metadata.privacy' | translate }}</label> <div class="col-md-4"> - <input type="text" class="form-control" name="type" - data-ng-model="document.privacy" disabled="disabled"/> + <select class="form-control" name="privacy" + ng-model="document.privacy"> + <option value="PRIVATE">{{ 'common.privacy.private' | translate }}</option> + <option value="PUBLIC">{{ 'common.privacy.public' | translate }}</option> + <option value="RESTRICTED">{{ 'common.privacy.restricted' | translate }}</option> + </select> + + <div ng-if="document.privacy == 'RESTRICTED'"> + {{ 'document.metadata.restricted.info' | 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> </div> -- 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 8071f4691e7c46a0f5cc98cda8df7e2c10494f71 Author: Yannick Martel <martel@©odelutin.com> Date: Thu Feb 5 11:37:29 2015 +0100 add API to get experts list, available for expert users --- .../coselmar/services/v1/UsersWebService.java | 46 ++++++++++++++++++++++ coselmar-rest/src/main/resources/mapping | 1 + coselmar-ui/src/main/webapp/i18n/en.js | 1 + coselmar-ui/src/main/webapp/i18n/fr.js | 1 + .../src/main/webapp/js/coselmar-controllers.js | 4 +- .../src/main/webapp/js/coselmar-services.js | 4 +- .../main/webapp/views/documents/editDocument.html | 2 +- .../main/webapp/views/documents/newdocument.html | 2 +- 8 files changed, 55 insertions(+), 6 deletions(-) diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UsersWebService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/UsersWebService.java index a3deee0..c0dbe5c 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 @@ -152,6 +152,52 @@ public class UsersWebService extends CoselmarWebServiceSupport { return result; } + public List<UserBean> getExperts(UserSearchBean search) throws InvalidCredentialException, UnauthorizedException { + + // Check authentication + String authorization = getContext().getHeader("Authorization"); + CoselmarUser currentUser = checkUserAuthentication(authorization); + + // Who is allowed here ? Admin and user himself + if (currentUser.getRole() != CoselmarUserRole.ADMIN + && currentUser.getRole() != CoselmarUserRole.SUPERVISOR + && currentUser.getRole() != CoselmarUserRole.EXPERT) { + if (log.isDebugEnabled()) { + String message = String.format("A non admin, non supervisor, non expert user is trying to access experts list"); + log.debug(message); + } + throw new UnauthorizedException("Not allowed to see experts"); + } + + List<CoselmarUser> userList; + if (search != null) { + // Search default parameter if not given + SearchRequestBean requestBean = new SearchRequestBean(); + requestBean.setLimit(search.getLimit()); + requestBean.setPage(search.getPage()); + requestBean.setFullTextSearch(search.getFullTextSearch()); + + CoselmarUser example = BeanEntityConverter.fromBean(search); + example.setRole(CoselmarUserRole.EXPERT);// we search experts here, force it ! + + userList = getCoselmarUserDao().findAllByExample(example, search.isActiveAndInactive(), requestBean); + + } else { + userList = getCoselmarUserDao().forRoleEquals(CoselmarUserRole.EXPERT).findAll(); + + } + + List<UserBean> result = new ArrayList<>(userList.size()); + + for (CoselmarUser user : userList) { + String userLightId = getPersistenceContext().getTopiaIdFactory().getRandomPart(user.getTopiaId()); + UserBean userBean = BeanEntityConverter.toBean(userLightId, user); + result.add(userBean); + } + + return result; + } + public void addUser(UserBean user) throws InvalidParameterException, InvalidCredentialException, UnauthorizedException { Preconditions.checkNotNull(user); diff --git a/coselmar-rest/src/main/resources/mapping b/coselmar-rest/src/main/resources/mapping index f0fd0df..3d166f2 100644 --- a/coselmar-rest/src/main/resources/mapping +++ b/coselmar-rest/src/main/resources/mapping @@ -43,6 +43,7 @@ DELETE /v1/documents/{documentId} DocumentsWebService.deleteDocume # Users Api GET /v1/users UsersWebService.getUsers +GET /v1/users/experts UsersWebService.getExperts GET /v1/users/{userId} UsersWebService.getUser POST /v1/users/login UsersWebService.login POST /v1/users/password UsersWebService.generateNewPassword diff --git a/coselmar-ui/src/main/webapp/i18n/en.js b/coselmar-ui/src/main/webapp/i18n/en.js index 457b4cd..6029427 100644 --- a/coselmar-ui/src/main/webapp/i18n/en.js +++ b/coselmar-ui/src/main/webapp/i18n/en.js @@ -107,6 +107,7 @@ var translateEN = { "document.message.requiredCopyright" : "Document copyright is required.", "document.message.requiredSummary" : "A summary is required.", "document.privacy.questionRestricted" : "Restricted to Project participants", +"document.privacy.restricted.info" : "Restricted to selected experts and to projects using document", "document.button.download" : "Download", "document.button.openLink" : "Open link", diff --git a/coselmar-ui/src/main/webapp/i18n/fr.js b/coselmar-ui/src/main/webapp/i18n/fr.js index 170d3da..ba6c83f 100644 --- a/coselmar-ui/src/main/webapp/i18n/fr.js +++ b/coselmar-ui/src/main/webapp/i18n/fr.js @@ -107,6 +107,7 @@ var translateFR = { "document.message.requiredCopyright" : "Le copyright du document est requis.", "document.message.requiredSummary" : "Un résumé est requis.", "document.privacy.questionRestricted" : "Restreint aux participants de projet.", +"document.privacy.restricted.info" : "Restreint aux experts indiqués et aux projets incluant le document", "document.button.download" : "Télécharger", "document.button.openLink" : "Ouvrir le lien", diff --git a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js index 8c23c11..2dad51f 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js @@ -158,7 +158,7 @@ coselmarControllers.controller("NewDocumentCtrl", ['$scope', '$location', 'docum searchKeywords.push(searchKeyword); } - documentService.findUsers({'role': 'EXPERT', 'active': true, 'fullTextSearch' : searchKeywords}, function(users) { + documentService.findExperts({'active': true, 'fullTextSearch' : searchKeywords}, function(users) { $scope.users = users; $scope.usersIndex = []; angular.forEach($scope.users, function(user) { @@ -349,7 +349,7 @@ coselmarControllers.controller("DocumentViewCtrl", searchKeywords.push(searchKeyword); } - documentService.findUsers({'role': 'EXPERT', 'active': true, 'fullTextSearch' : searchKeywords}, function(users) { + documentService.findExperts({'active': true, 'fullTextSearch' : searchKeywords}, function(users) { $scope.users = users; $scope.usersIndex = []; angular.forEach($scope.users, function(user) { diff --git a/coselmar-ui/src/main/webapp/js/coselmar-services.js b/coselmar-ui/src/main/webapp/js/coselmar-services.js index 6e2f2f7..815cfc0 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-services.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-services.js @@ -130,8 +130,8 @@ function Document(resource, config){ docResource.query(successFunction); }; - this.findUsers = function(example, successFunction) { - var userResource = resource(usersURL, {'search': example}); + this.findExperts = function(example, successFunction) { + var userResource = resource(usersURL + '/experts', {'search': example}); userResource.query(successFunction); }; diff --git a/coselmar-ui/src/main/webapp/views/documents/editDocument.html b/coselmar-ui/src/main/webapp/views/documents/editDocument.html index 7764bc8..caf807c 100644 --- a/coselmar-ui/src/main/webapp/views/documents/editDocument.html +++ b/coselmar-ui/src/main/webapp/views/documents/editDocument.html @@ -103,7 +103,7 @@ </select> <div ng-if="document.privacy == 'RESTRICTED'"> - {{ 'document.metadata.restricted.info' | translate }} + {{ 'document.privacy.restricted.info' | translate }} <ui-select multiple ng-model="document.authorizedUsers" theme="bootstrap" reset-search-input="true" diff --git a/coselmar-ui/src/main/webapp/views/documents/newdocument.html b/coselmar-ui/src/main/webapp/views/documents/newdocument.html index 96da0c7..132e1af 100644 --- a/coselmar-ui/src/main/webapp/views/documents/newdocument.html +++ b/coselmar-ui/src/main/webapp/views/documents/newdocument.html @@ -112,7 +112,7 @@ </select> <div ng-if="document.privacy == 'RESTRICTED'"> - {{ 'document.metadata.restricted.info' | translate }} + {{ 'document.privacy.restricted.info' | translate }} <ui-select multiple ng-model="document.authorizedUsers" theme="bootstrap" reset-search-input="true" -- 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 0667fa1f1cd2db32d3ec82c03deb94e478cf911b Merge: 8071f46 43e514c Author: Yannick Martel <martel@©odelutin.com> Date: Thu Feb 5 11:38:19 2015 +0100 Merge branch 'develop' into feature/6515-restrected-access-on-document coselmar-ui/src/main/webapp/i18n/fr.js | 4 ++-- 1 file changed, 2 insertions(+), 2 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 2ae6ffac13d650ca6af0bcb2fadd7babb1102a83 Merge: 43e514c 0667fa1 Author: Yannick Martel <martel@©odelutin.com> Date: Thu Feb 5 11:38:55 2015 +0100 Fixes #6515 Merge branch 'feature/6515-restrected-access-on-document' into develop .../persistence/entity/DocumentTopiaDao.java | 13 +- .../fr/ifremer/coselmar/beans/DocumentBean.java | 19 ++ .../services/CoselmarWebServiceSupport.java | 77 ++++++++- .../coselmar/services/v1/DocumentsWebService.java | 192 ++++++++++++++++----- .../coselmar/services/v1/QuestionsWebService.java | 83 +++++++-- .../coselmar/services/v1/UsersWebService.java | 46 +++++ coselmar-rest/src/main/resources/mapping | 1 + coselmar-ui/src/main/webapp/i18n/en.js | 1 + coselmar-ui/src/main/webapp/i18n/fr.js | 1 + .../src/main/webapp/js/coselmar-controllers.js | 71 +++++++- .../main/webapp/js/coselmar-questions-services.js | 2 - .../src/main/webapp/js/coselmar-services.js | 7 + .../main/webapp/views/documents/editDocument.html | 28 ++- .../main/webapp/views/documents/newdocument.html | 18 +- 14 files changed, 484 insertions(+), 75 deletions(-) -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
participants (1)
-
codelutin.com scm