mirror of
https://github.com/sismics/docs.git
synced 2024-11-22 14:07:55 +01:00
#18: Group resource, groups handling in ACL, groups returned in users
This commit is contained in:
parent
43a1575187
commit
a5ce5bf9ec
@ -28,6 +28,7 @@ Features
|
|||||||
- 256-bit AES encryption
|
- 256-bit AES encryption
|
||||||
- Tag system with relations
|
- Tag system with relations
|
||||||
- Multi-users ACL system
|
- Multi-users ACL system
|
||||||
|
- Hierarchical groups
|
||||||
- Audit log
|
- Audit log
|
||||||
- Comments
|
- Comments
|
||||||
- Storage quota per user
|
- Storage quota per user
|
||||||
|
@ -68,10 +68,11 @@ public class AclDao {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public List<AclDto> getBySourceId(String sourceId) {
|
public List<AclDto> getBySourceId(String sourceId) {
|
||||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
StringBuilder sb = new StringBuilder("select a.ACL_ID_C, a.ACL_PERM_C, a.ACL_TARGETID_C, u.USE_USERNAME_C, s.SHA_NAME_C");
|
StringBuilder sb = new StringBuilder("select a.ACL_ID_C, a.ACL_PERM_C, a.ACL_TARGETID_C, u.USE_USERNAME_C, s.SHA_NAME_C, g.GRP_NAME_C ");
|
||||||
sb.append(" from T_ACL a ");
|
sb.append(" from T_ACL a ");
|
||||||
sb.append(" left join T_USER u on u.USE_ID_C = a.ACL_TARGETID_C ");
|
sb.append(" left join T_USER u on u.USE_ID_C = a.ACL_TARGETID_C ");
|
||||||
sb.append(" left join T_SHARE s on s.SHA_ID_C = a.ACL_TARGETID_C ");
|
sb.append(" left join T_SHARE s on s.SHA_ID_C = a.ACL_TARGETID_C ");
|
||||||
|
sb.append(" left join T_GROUP g on g.GRP_ID_C = a.ACL_TARGETID_C ");
|
||||||
sb.append(" where a.ACL_DELETEDATE_D is null and a.ACL_SOURCEID_C = :sourceId ");
|
sb.append(" where a.ACL_DELETEDATE_D is null and a.ACL_SOURCEID_C = :sourceId ");
|
||||||
|
|
||||||
// Perform the query
|
// Perform the query
|
||||||
@ -89,9 +90,19 @@ public class AclDao {
|
|||||||
aclDto.setTargetId((String) o[i++]);
|
aclDto.setTargetId((String) o[i++]);
|
||||||
String userName = (String) o[i++];
|
String userName = (String) o[i++];
|
||||||
String shareName = (String) o[i++];
|
String shareName = (String) o[i++];
|
||||||
aclDto.setTargetName(userName == null ? shareName : userName);
|
String groupName = (String) o[i++];
|
||||||
aclDto.setTargetType(userName == null ?
|
if (userName != null) {
|
||||||
AclTargetType.SHARE.name() : AclTargetType.USER.name());
|
aclDto.setTargetName(userName);
|
||||||
|
aclDto.setTargetType(AclTargetType.USER.name());
|
||||||
|
}
|
||||||
|
if (shareName != null) {
|
||||||
|
aclDto.setTargetName(shareName);
|
||||||
|
aclDto.setTargetType(AclTargetType.SHARE.name());
|
||||||
|
}
|
||||||
|
if (groupName != null) {
|
||||||
|
aclDto.setTargetName(groupName);
|
||||||
|
aclDto.setTargetType(AclTargetType.GROUP.name());
|
||||||
|
}
|
||||||
aclDtoList.add(aclDto);
|
aclDtoList.add(aclDto);
|
||||||
}
|
}
|
||||||
return aclDtoList;
|
return aclDtoList;
|
||||||
|
@ -92,13 +92,14 @@ public class DocumentDao {
|
|||||||
*/
|
*/
|
||||||
public DocumentDto getDocument(String id, PermType perm, List<String> targetIdList) {
|
public DocumentDto getDocument(String id, PermType perm, List<String> targetIdList) {
|
||||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
StringBuilder sb = new StringBuilder("select d.DOC_ID_C, d.DOC_TITLE_C, d.DOC_DESCRIPTION_C, d.DOC_SUBJECT_C, d.DOC_IDENTIFIER_C, d.DOC_PUBLISHER_C, d.DOC_FORMAT_C, d.DOC_SOURCE_C, d.DOC_TYPE_C, d.DOC_COVERAGE_C, d.DOC_RIGHTS_C, d.DOC_CREATEDATE_D, d.DOC_LANGUAGE_C, ");
|
StringBuilder sb = new StringBuilder("select distinct d.DOC_ID_C, d.DOC_TITLE_C, d.DOC_DESCRIPTION_C, d.DOC_SUBJECT_C, d.DOC_IDENTIFIER_C, d.DOC_PUBLISHER_C, d.DOC_FORMAT_C, d.DOC_SOURCE_C, d.DOC_TYPE_C, d.DOC_COVERAGE_C, d.DOC_RIGHTS_C, d.DOC_CREATEDATE_D, d.DOC_LANGUAGE_C, ");
|
||||||
sb.append(" (select count(s.SHA_ID_C) from T_SHARE s, T_ACL ac where ac.ACL_SOURCEID_C = d.DOC_ID_C and ac.ACL_TARGETID_C = s.SHA_ID_C and ac.ACL_DELETEDATE_D is null and s.SHA_DELETEDATE_D is null), ");
|
sb.append(" (select count(s.SHA_ID_C) from T_SHARE s, T_ACL ac where ac.ACL_SOURCEID_C = d.DOC_ID_C and ac.ACL_TARGETID_C = s.SHA_ID_C and ac.ACL_DELETEDATE_D is null and s.SHA_DELETEDATE_D is null), ");
|
||||||
sb.append(" (select count(f.FIL_ID_C) from T_FILE f where f.FIL_DELETEDATE_D is null and f.FIL_IDDOC_C = d.DOC_ID_C), ");
|
sb.append(" (select count(f.FIL_ID_C) from T_FILE f where f.FIL_DELETEDATE_D is null and f.FIL_IDDOC_C = d.DOC_ID_C), ");
|
||||||
sb.append(" u.USE_USERNAME_C ");
|
sb.append(" u.USE_USERNAME_C ");
|
||||||
sb.append(" from T_DOCUMENT d, T_USER u ");
|
sb.append(" from T_DOCUMENT d ");
|
||||||
sb.append(" join T_ACL a on a.ACL_SOURCEID_C = d.DOC_ID_C and a.ACL_TARGETID_C in (:targetIdList) and a.ACL_PERM_C = :perm and a.ACL_DELETEDATE_D is null ");
|
sb.append(" join T_USER u on d.DOC_IDUSER_C = u.USE_ID_C ");
|
||||||
sb.append(" where d.DOC_IDUSER_C = u.USE_ID_C and d.DOC_ID_C = :id and d.DOC_DELETEDATE_D is null ");
|
sb.append(" left join T_ACL a on a.ACL_SOURCEID_C = d.DOC_ID_C and a.ACL_TARGETID_C in (:targetIdList) and a.ACL_PERM_C = :perm and a.ACL_DELETEDATE_D is null ");
|
||||||
|
sb.append(" where d.DOC_ID_C = :id and a.ACL_ID_C is not null and d.DOC_DELETEDATE_D is null ");
|
||||||
|
|
||||||
Query q = em.createNativeQuery(sb.toString());
|
Query q = em.createNativeQuery(sb.toString());
|
||||||
q.setParameter("id", id);
|
q.setParameter("id", id);
|
||||||
|
@ -1,16 +1,28 @@
|
|||||||
package com.sismics.docs.core.dao.jpa;
|
package com.sismics.docs.core.dao.jpa;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.NoResultException;
|
import javax.persistence.NoResultException;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
import com.sismics.docs.core.constant.AuditLogType;
|
import com.sismics.docs.core.constant.AuditLogType;
|
||||||
|
import com.sismics.docs.core.dao.jpa.criteria.GroupCriteria;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.GroupDto;
|
||||||
import com.sismics.docs.core.model.jpa.Group;
|
import com.sismics.docs.core.model.jpa.Group;
|
||||||
import com.sismics.docs.core.model.jpa.UserGroup;
|
import com.sismics.docs.core.model.jpa.UserGroup;
|
||||||
import com.sismics.docs.core.util.AuditLogUtil;
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
|
import com.sismics.docs.core.util.jpa.QueryParam;
|
||||||
|
import com.sismics.docs.core.util.jpa.QueryUtil;
|
||||||
|
import com.sismics.docs.core.util.jpa.SortCriteria;
|
||||||
import com.sismics.util.context.ThreadLocalContext;
|
import com.sismics.util.context.ThreadLocalContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,7 +37,7 @@ public class GroupDao {
|
|||||||
* @param name Name
|
* @param name Name
|
||||||
* @return Tag
|
* @return Tag
|
||||||
*/
|
*/
|
||||||
public Group getByName(String name) {
|
public Group getActiveByName(String name) {
|
||||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
Query q = em.createQuery("select g from Group g where g.name = :name and g.deleteDate is null");
|
Query q = em.createQuery("select g from Group g where g.name = :name and g.deleteDate is null");
|
||||||
q.setParameter("name", name);
|
q.setParameter("name", name);
|
||||||
@ -81,6 +93,11 @@ public class GroupDao {
|
|||||||
q.setParameter("dateNow", dateNow);
|
q.setParameter("dateNow", dateNow);
|
||||||
q.setParameter("groupId", groupId);
|
q.setParameter("groupId", groupId);
|
||||||
q.executeUpdate();
|
q.executeUpdate();
|
||||||
|
|
||||||
|
q = em.createQuery("update Acl a set a.deleteDate = :dateNow where a.targetId = :groupId and a.deleteDate is null");
|
||||||
|
q.setParameter("groupId", groupDb.getId());
|
||||||
|
q.setParameter("dateNow", dateNow);
|
||||||
|
q.executeUpdate();
|
||||||
|
|
||||||
// Create audit log
|
// Create audit log
|
||||||
AuditLogUtil.create(groupDb, AuditLogType.DELETE, userId);
|
AuditLogUtil.create(groupDb, AuditLogType.DELETE, userId);
|
||||||
@ -108,18 +125,107 @@ public class GroupDao {
|
|||||||
* Remove an user from a group.
|
* Remove an user from a group.
|
||||||
*
|
*
|
||||||
* @param groupId Group ID
|
* @param groupId Group ID
|
||||||
|
* @param userId User ID
|
||||||
*/
|
*/
|
||||||
public void removeMember(String userGroupId) {
|
public void removeMember(String groupId, String userId) {
|
||||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
|
|
||||||
// Get the user group
|
// Get the user group
|
||||||
Query q = em.createQuery("select ug from UserGroup ug where ug.id = :id and ug.deleteDate is null");
|
Query q = em.createQuery("select ug from UserGroup ug where ug.groupId = :groupId and ug.userId = :userId and ug.deleteDate is null");
|
||||||
q.setParameter("id", userGroupId);
|
q.setParameter("groupId", groupId);
|
||||||
|
q.setParameter("userId", userId);
|
||||||
UserGroup userGroupDb = (UserGroup) q.getSingleResult();
|
UserGroup userGroupDb = (UserGroup) q.getSingleResult();
|
||||||
|
|
||||||
// Delete the user group
|
// Delete the user group
|
||||||
Date dateNow = new Date();
|
Date dateNow = new Date();
|
||||||
userGroupDb.setDeleteDate(dateNow);
|
userGroupDb.setDeleteDate(dateNow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of all groups.
|
||||||
|
*
|
||||||
|
* @param criteria Search criteria
|
||||||
|
* @param sortCriteria Sort criteria
|
||||||
|
* @return List of groups
|
||||||
|
*/
|
||||||
|
public List<GroupDto> findByCriteria(GroupCriteria criteria, SortCriteria sortCriteria) {
|
||||||
|
Map<String, Object> parameterMap = new HashMap<String, Object>();
|
||||||
|
List<String> criteriaList = new ArrayList<String>();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder("select g.GRP_ID_C as c0, g.GRP_NAME_C as c1, g.GRP_IDPARENT_C as c2, ug.UGP_ID_C ");
|
||||||
|
sb.append(" from T_GROUP g ");
|
||||||
|
|
||||||
|
// Add search criterias
|
||||||
|
if (criteria.getSearch() != null) {
|
||||||
|
criteriaList.add("lower(g.GRP_NAME_C) like lower(:search)");
|
||||||
|
parameterMap.put("search", "%" + criteria.getSearch() + "%");
|
||||||
|
}
|
||||||
|
if (criteria.getUserId() != null) {
|
||||||
|
// Left join and post-filtering for recursive groups
|
||||||
|
sb.append((criteria.isRecursive() ? " left " : "")
|
||||||
|
+ " join T_USER_GROUP ug on ug.UGP_IDGROUP_C = g.GRP_ID_C and ug.UGP_IDUSER_C = :userId and ug.UGP_DELETEDATE_D is null ");
|
||||||
|
parameterMap.put("userId", criteria.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
criteriaList.add("g.GRP_DELETEDATE_D is null");
|
||||||
|
|
||||||
|
if (!criteriaList.isEmpty()) {
|
||||||
|
sb.append(" where ");
|
||||||
|
sb.append(Joiner.on(" and ").join(criteriaList));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the search
|
||||||
|
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Object[]> l = QueryUtil.getNativeQuery(queryParam).getResultList();
|
||||||
|
|
||||||
|
// Assemble results
|
||||||
|
List<GroupDto> groupDtoList = new ArrayList<>();
|
||||||
|
List<GroupDto> userGroupDtoList = new ArrayList<>();
|
||||||
|
for (Object[] o : l) {
|
||||||
|
int i = 0;
|
||||||
|
GroupDto groupDto = new GroupDto()
|
||||||
|
.setId((String) o[i++])
|
||||||
|
.setName((String) o[i++])
|
||||||
|
.setParentId((String) o[i++]);
|
||||||
|
groupDtoList.add(groupDto);
|
||||||
|
if (o[i++] != null) {
|
||||||
|
userGroupDtoList.add(groupDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post-query filtering for recursive groups
|
||||||
|
if (criteria.getUserId() != null && criteria.isRecursive()) {
|
||||||
|
Set<GroupDto> filteredGroupDtoSet = new HashSet<>();
|
||||||
|
for (GroupDto userGroupDto : userGroupDtoList) {
|
||||||
|
filteredGroupDtoSet.add(userGroupDto); // Direct group
|
||||||
|
findGroupParentHierarchy(filteredGroupDtoSet, groupDtoList, userGroupDto, 0); // Indirect groups
|
||||||
|
}
|
||||||
|
groupDtoList = new ArrayList<>(filteredGroupDtoSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
return groupDtoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively search group's parents.
|
||||||
|
*
|
||||||
|
* @param parentGroupDtoSet Resulting parents
|
||||||
|
* @param groupDtoList All groups
|
||||||
|
* @param userGroupDto Reference group to search from
|
||||||
|
* @param depth Depth
|
||||||
|
*/
|
||||||
|
private void findGroupParentHierarchy(Set<GroupDto> parentGroupDtoSet, List<GroupDto> groupDtoList, GroupDto userGroupDto, int depth) {
|
||||||
|
if (userGroupDto.getParentId() == null || depth == 10) { // Max depth 10 to avoid infinite loop
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (GroupDto groupDto : groupDtoList) {
|
||||||
|
if (groupDto.getId().equals(userGroupDto.getParentId())) {
|
||||||
|
parentGroupDtoSet.add(groupDto); // Add parent
|
||||||
|
findGroupParentHierarchy(parentGroupDtoSet, groupDtoList, groupDto, depth + 1); // Find parent's parents
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,9 +20,8 @@ import com.sismics.docs.core.dao.jpa.criteria.UserCriteria;
|
|||||||
import com.sismics.docs.core.dao.jpa.dto.UserDto;
|
import com.sismics.docs.core.dao.jpa.dto.UserDto;
|
||||||
import com.sismics.docs.core.model.jpa.User;
|
import com.sismics.docs.core.model.jpa.User;
|
||||||
import com.sismics.docs.core.util.AuditLogUtil;
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedList;
|
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
|
||||||
import com.sismics.docs.core.util.jpa.QueryParam;
|
import com.sismics.docs.core.util.jpa.QueryParam;
|
||||||
|
import com.sismics.docs.core.util.jpa.QueryUtil;
|
||||||
import com.sismics.docs.core.util.jpa.SortCriteria;
|
import com.sismics.docs.core.util.jpa.SortCriteria;
|
||||||
import com.sismics.util.context.ThreadLocalContext;
|
import com.sismics.util.context.ThreadLocalContext;
|
||||||
|
|
||||||
@ -265,10 +264,11 @@ public class UserDao {
|
|||||||
/**
|
/**
|
||||||
* Returns the list of all users.
|
* Returns the list of all users.
|
||||||
*
|
*
|
||||||
* @param paginatedList List of users (updated by side effects)
|
* @param criteria Search criteria
|
||||||
* @param sortCriteria Sort criteria
|
* @param sortCriteria Sort criteria
|
||||||
|
* @return List of users
|
||||||
*/
|
*/
|
||||||
public void findByCriteria(PaginatedList<UserDto> paginatedList, UserCriteria criteria, SortCriteria sortCriteria) {
|
public List<UserDto> findByCriteria(UserCriteria criteria, SortCriteria sortCriteria) {
|
||||||
Map<String, Object> parameterMap = new HashMap<String, Object>();
|
Map<String, Object> parameterMap = new HashMap<String, Object>();
|
||||||
List<String> criteriaList = new ArrayList<String>();
|
List<String> criteriaList = new ArrayList<String>();
|
||||||
|
|
||||||
@ -289,8 +289,9 @@ public class UserDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform the search
|
// Perform the search
|
||||||
QueryParam queryParam = new QueryParam(sb.toString(), parameterMap);
|
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
||||||
List<Object[]> l = PaginatedLists.executePaginatedQuery(paginatedList, queryParam, sortCriteria);
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Object[]> l = QueryUtil.getNativeQuery(queryParam).getResultList();
|
||||||
|
|
||||||
// Assemble results
|
// Assemble results
|
||||||
List<UserDto> userDtoList = new ArrayList<UserDto>();
|
List<UserDto> userDtoList = new ArrayList<UserDto>();
|
||||||
@ -305,6 +306,6 @@ public class UserDao {
|
|||||||
userDto.setStorageQuota(((Number) o[i++]).longValue());
|
userDto.setStorageQuota(((Number) o[i++]).longValue());
|
||||||
userDtoList.add(userDto);
|
userDtoList.add(userDto);
|
||||||
}
|
}
|
||||||
paginatedList.setResultList(userDtoList);
|
return userDtoList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.sismics.docs.core.dao.jpa.criteria;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group criteria.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class GroupCriteria {
|
||||||
|
/**
|
||||||
|
* Search query.
|
||||||
|
*/
|
||||||
|
private String search;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User ID.
|
||||||
|
*/
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve user groups recursively.
|
||||||
|
*/
|
||||||
|
private boolean recursive = false;
|
||||||
|
|
||||||
|
public String getSearch() {
|
||||||
|
return search;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupCriteria setSearch(String search) {
|
||||||
|
this.search = search;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupCriteria setUserId(String userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRecursive() {
|
||||||
|
return recursive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupCriteria setRecursive(boolean recursive) {
|
||||||
|
this.recursive = recursive;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,5 @@
|
|||||||
package com.sismics.docs.core.dao.jpa.criteria;
|
package com.sismics.docs.core.dao.jpa.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User criteria.
|
* User criteria.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.sismics.docs.core.dao.jpa.dto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group DTO.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class GroupDto {
|
||||||
|
/**
|
||||||
|
* Group ID.
|
||||||
|
*/
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent ID.
|
||||||
|
*/
|
||||||
|
private String parentId;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupDto setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupDto setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParentId() {
|
||||||
|
return parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupDto setParentId(String parentId) {
|
||||||
|
this.parentId = parentId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return id.equals(((GroupDto) obj).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id.hashCode();
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package com.sismics.docs.core.dao.jpa.dto;
|
package com.sismics.docs.core.dao.jpa.dto;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User DTO.
|
* User DTO.
|
||||||
*
|
*
|
||||||
|
@ -105,13 +105,7 @@ public class PaginatedLists {
|
|||||||
* @return List of results
|
* @return List of results
|
||||||
*/
|
*/
|
||||||
public static <E> List<Object[]> executePaginatedQuery(PaginatedList<E> paginatedList, QueryParam queryParam, SortCriteria sortCriteria) {
|
public static <E> List<Object[]> executePaginatedQuery(PaginatedList<E> paginatedList, QueryParam queryParam, SortCriteria sortCriteria) {
|
||||||
StringBuilder sb = new StringBuilder(queryParam.getQueryString());
|
QueryParam sortedQueryParam = QueryUtil.getSortedQueryParam(queryParam, sortCriteria);
|
||||||
sb.append(" order by c");
|
|
||||||
sb.append(sortCriteria.getColumn());
|
|
||||||
sb.append(sortCriteria.isAsc() ? " asc" : " desc");
|
|
||||||
|
|
||||||
QueryParam sortedQueryParam = new QueryParam(sb.toString(), queryParam.getParameterMap());
|
|
||||||
|
|
||||||
executeCountQuery(paginatedList, sortedQueryParam);
|
executeCountQuery(paginatedList, sortedQueryParam);
|
||||||
return executeResultQuery(paginatedList, sortedQueryParam);
|
return executeResultQuery(paginatedList, sortedQueryParam);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package com.sismics.docs.core.util.jpa;
|
package com.sismics.docs.core.util.jpa;
|
||||||
|
|
||||||
import com.sismics.util.context.ThreadLocalContext;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
import com.sismics.util.context.ThreadLocalContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query utilities.
|
* Query utilities.
|
||||||
@ -27,4 +28,22 @@ public class QueryUtil {
|
|||||||
}
|
}
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns sorted query parameters.
|
||||||
|
*
|
||||||
|
* @param queryParam Query parameters
|
||||||
|
* @param sortCriteria Sort criteria
|
||||||
|
* @return Sorted query parameters
|
||||||
|
*/
|
||||||
|
public static QueryParam getSortedQueryParam(QueryParam queryParam, SortCriteria sortCriteria) {
|
||||||
|
StringBuilder sb = new StringBuilder(queryParam.getQueryString());
|
||||||
|
if (sortCriteria != null) {
|
||||||
|
sb.append(" order by c");
|
||||||
|
sb.append(sortCriteria.getColumn());
|
||||||
|
sb.append(sortCriteria.isAsc() ? " asc" : " desc");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryParam(sb.toString(), queryParam.getParameterMap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package com.sismics.security;
|
package com.sismics.security;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import jersey.repackaged.com.google.common.collect.Sets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Anonymous principal.
|
* Anonymous principal.
|
||||||
@ -56,7 +56,7 @@ public class AnonymousPrincipal implements IPrincipal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getGroupIdList() {
|
public Set<String> getGroupIdSet() {
|
||||||
return Lists.newArrayList();
|
return Sets.newHashSet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.sismics.security;
|
package com.sismics.security;
|
||||||
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ public interface IPrincipal extends Principal {
|
|||||||
*
|
*
|
||||||
* @return List of group ID
|
* @return List of group ID
|
||||||
*/
|
*/
|
||||||
public List<String> getGroupIdList();
|
public Set<String> getGroupIdSet();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the timezone of the principal.
|
* Returns the timezone of the principal.
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
package com.sismics.security;
|
package com.sismics.security;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
|
|
||||||
import jersey.repackaged.com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticated users principal.
|
* Authenticated users principal.
|
||||||
*
|
*
|
||||||
@ -38,6 +35,11 @@ public class UserPrincipal implements IPrincipal {
|
|||||||
*/
|
*/
|
||||||
private Set<String> baseFunctionSet;
|
private Set<String> baseFunctionSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User groups.
|
||||||
|
*/
|
||||||
|
private Set<String> groupIdSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor of UserPrincipal.
|
* Constructor of UserPrincipal.
|
||||||
*
|
*
|
||||||
@ -99,8 +101,11 @@ public class UserPrincipal implements IPrincipal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getGroupIdList() {
|
public Set<String> getGroupIdSet() {
|
||||||
// TODO Real groups
|
return groupIdSet;
|
||||||
return Lists.newArrayList("members");
|
}
|
||||||
|
|
||||||
|
public void setGroupIdSet(Set<String> groupIdSet) {
|
||||||
|
this.groupIdSet = groupIdSet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.sismics.util.filter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
@ -20,14 +21,18 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import com.sismics.docs.core.constant.Constants;
|
import com.sismics.docs.core.constant.Constants;
|
||||||
import com.sismics.docs.core.dao.jpa.AuthenticationTokenDao;
|
import com.sismics.docs.core.dao.jpa.AuthenticationTokenDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.GroupDao;
|
||||||
import com.sismics.docs.core.dao.jpa.RoleBaseFunctionDao;
|
import com.sismics.docs.core.dao.jpa.RoleBaseFunctionDao;
|
||||||
import com.sismics.docs.core.dao.jpa.UserDao;
|
import com.sismics.docs.core.dao.jpa.UserDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.criteria.GroupCriteria;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.GroupDto;
|
||||||
import com.sismics.docs.core.model.jpa.AuthenticationToken;
|
import com.sismics.docs.core.model.jpa.AuthenticationToken;
|
||||||
import com.sismics.docs.core.model.jpa.User;
|
import com.sismics.docs.core.model.jpa.User;
|
||||||
import com.sismics.docs.core.util.TransactionUtil;
|
|
||||||
import com.sismics.security.AnonymousPrincipal;
|
import com.sismics.security.AnonymousPrincipal;
|
||||||
import com.sismics.security.UserPrincipal;
|
import com.sismics.security.UserPrincipal;
|
||||||
|
|
||||||
|
import jersey.repackaged.com.google.common.collect.Sets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This filter is used to authenticate the user having an active session via an authentication token stored in database.
|
* This filter is used to authenticate the user having an active session via an authentication token stored in database.
|
||||||
* The filter extracts the authentication token stored in a cookie.
|
* The filter extracts the authentication token stored in a cookie.
|
||||||
@ -113,10 +118,6 @@ public class TokenBasedSecurityFilter implements Filter {
|
|||||||
User user = userDao.getById(authenticationToken.getUserId());
|
User user = userDao.getById(authenticationToken.getUserId());
|
||||||
if (user != null && user.getDeleteDate() == null) {
|
if (user != null && user.getDeleteDate() == null) {
|
||||||
injectAuthenticatedUser(request, user);
|
injectAuthenticatedUser(request, user);
|
||||||
|
|
||||||
// Update the last connection date
|
|
||||||
authenticationTokenDao.updateLastConnectionDate(authenticationToken.getId());
|
|
||||||
TransactionUtil.commit();
|
|
||||||
} else {
|
} else {
|
||||||
injectAnonymousUser(request);
|
injectAnonymousUser(request);
|
||||||
}
|
}
|
||||||
@ -158,6 +159,17 @@ public class TokenBasedSecurityFilter implements Filter {
|
|||||||
Set<String> baseFunctionSet = userBaseFuction.findByRoleId(user.getRoleId());
|
Set<String> baseFunctionSet = userBaseFuction.findByRoleId(user.getRoleId());
|
||||||
userPrincipal.setBaseFunctionSet(baseFunctionSet);
|
userPrincipal.setBaseFunctionSet(baseFunctionSet);
|
||||||
|
|
||||||
|
// Add groups
|
||||||
|
GroupDao groupDao = new GroupDao();
|
||||||
|
List<GroupDto> groupDtoList = groupDao.findByCriteria(new GroupCriteria()
|
||||||
|
.setUserId(user.getId())
|
||||||
|
.setRecursive(true), null);
|
||||||
|
Set<String> groupIdSet = Sets.newHashSet();
|
||||||
|
for (GroupDto groupDto : groupDtoList) {
|
||||||
|
groupIdSet.add(groupDto.getId());
|
||||||
|
}
|
||||||
|
userPrincipal.setGroupIdSet(groupIdSet);
|
||||||
|
|
||||||
// Add email
|
// Add email
|
||||||
userPrincipal.setEmail(user.getEmail());
|
userPrincipal.setEmail(user.getEmail());
|
||||||
|
|
||||||
|
@ -31,22 +31,59 @@ public class ClientUtil {
|
|||||||
*
|
*
|
||||||
* @param username Username
|
* @param username Username
|
||||||
*/
|
*/
|
||||||
public void createUser(String username) {
|
public void createUser(String username, String... groupNameList) {
|
||||||
// Login admin to create the user
|
// Login admin to create the user
|
||||||
String adminAuthenticationToken = login("admin", "admin", false);
|
String adminToken = login("admin", "admin", false);
|
||||||
|
|
||||||
// Create the user
|
// Create the user
|
||||||
Form form = new Form();
|
|
||||||
form.param("username", username);
|
|
||||||
form.param("email", username + "@docs.com");
|
|
||||||
form.param("password", "12345678");
|
|
||||||
form.param("storage_quota", "1000000"); // 1MB quota
|
|
||||||
resource.path("/user").request()
|
resource.path("/user").request()
|
||||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
.put(Entity.form(form), JsonObject.class);
|
.put(Entity.form(new Form()
|
||||||
|
.param("username", username)
|
||||||
|
.param("email", username + "@docs.com")
|
||||||
|
.param("password", "12345678")
|
||||||
|
.param("storage_quota", "1000000")), JsonObject.class); // 1MB quota
|
||||||
|
|
||||||
|
// Add to groups
|
||||||
|
for (String groupName : groupNameList) {
|
||||||
|
resource.path("/group/" + groupName).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("username", username)), JsonObject.class);
|
||||||
|
}
|
||||||
|
|
||||||
// Logout admin
|
// Logout admin
|
||||||
logout(adminAuthenticationToken);
|
logout(adminToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a group.
|
||||||
|
*
|
||||||
|
* @param name Name
|
||||||
|
*/
|
||||||
|
public void createGroup(String name) {
|
||||||
|
createGroup(name, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a group.
|
||||||
|
*
|
||||||
|
* @param name Name
|
||||||
|
* @param parent Parent
|
||||||
|
*/
|
||||||
|
public void createGroup(String name, String parentId) {
|
||||||
|
// Login admin to create the group
|
||||||
|
String adminToken = login("admin", "admin", false);
|
||||||
|
|
||||||
|
// Create the gorup
|
||||||
|
resource.path("/group").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("name", name)
|
||||||
|
.param("parent", parentId)), JsonObject.class);
|
||||||
|
|
||||||
|
// Logout admin
|
||||||
|
logout(adminToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.sismics.docs.rest.resource;
|
package com.sismics.docs.rest.resource;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.json.Json;
|
import javax.json.Json;
|
||||||
import javax.json.JsonArrayBuilder;
|
import javax.json.JsonArrayBuilder;
|
||||||
@ -19,14 +20,16 @@ import com.sismics.docs.core.constant.AclTargetType;
|
|||||||
import com.sismics.docs.core.constant.PermType;
|
import com.sismics.docs.core.constant.PermType;
|
||||||
import com.sismics.docs.core.dao.jpa.AclDao;
|
import com.sismics.docs.core.dao.jpa.AclDao;
|
||||||
import com.sismics.docs.core.dao.jpa.DocumentDao;
|
import com.sismics.docs.core.dao.jpa.DocumentDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.GroupDao;
|
||||||
import com.sismics.docs.core.dao.jpa.UserDao;
|
import com.sismics.docs.core.dao.jpa.UserDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.criteria.GroupCriteria;
|
||||||
import com.sismics.docs.core.dao.jpa.criteria.UserCriteria;
|
import com.sismics.docs.core.dao.jpa.criteria.UserCriteria;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.GroupDto;
|
||||||
import com.sismics.docs.core.dao.jpa.dto.UserDto;
|
import com.sismics.docs.core.dao.jpa.dto.UserDto;
|
||||||
import com.sismics.docs.core.model.jpa.Acl;
|
import com.sismics.docs.core.model.jpa.Acl;
|
||||||
import com.sismics.docs.core.model.jpa.Document;
|
import com.sismics.docs.core.model.jpa.Document;
|
||||||
|
import com.sismics.docs.core.model.jpa.Group;
|
||||||
import com.sismics.docs.core.model.jpa.User;
|
import com.sismics.docs.core.model.jpa.User;
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedList;
|
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
|
||||||
import com.sismics.docs.core.util.jpa.SortCriteria;
|
import com.sismics.docs.core.util.jpa.SortCriteria;
|
||||||
import com.sismics.rest.exception.ClientException;
|
import com.sismics.rest.exception.ClientException;
|
||||||
import com.sismics.rest.exception.ForbiddenClientException;
|
import com.sismics.rest.exception.ForbiddenClientException;
|
||||||
@ -42,27 +45,52 @@ public class AclResource extends BaseResource {
|
|||||||
/**
|
/**
|
||||||
* Add an ACL.
|
* Add an ACL.
|
||||||
*
|
*
|
||||||
|
* @param sourceId Source ID
|
||||||
|
* @param permStr Permission
|
||||||
|
* @param targetName Target name
|
||||||
|
* @param type ACL type
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
@PUT
|
@PUT
|
||||||
public Response add(@FormParam("source") String sourceId,
|
public Response add(@FormParam("source") String sourceId,
|
||||||
@FormParam("perm") String permStr,
|
@FormParam("perm") String permStr,
|
||||||
@FormParam("username") String username) {
|
@FormParam("target") String targetName,
|
||||||
|
@FormParam("type") String typeStr) {
|
||||||
if (!authenticate()) {
|
if (!authenticate()) {
|
||||||
throw new ForbiddenClientException();
|
throw new ForbiddenClientException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Allow group input
|
|
||||||
// Validate input
|
// Validate input
|
||||||
ValidationUtil.validateRequired(sourceId, "source");
|
ValidationUtil.validateRequired(sourceId, "source");
|
||||||
PermType perm = PermType.valueOf(ValidationUtil.validateLength(permStr, "perm", 1, 30, false));
|
PermType perm = PermType.valueOf(ValidationUtil.validateLength(permStr, "perm", 1, 30, false));
|
||||||
username = ValidationUtil.validateLength(username, "username", 1, 50, false);
|
AclTargetType type = AclTargetType.valueOf(ValidationUtil.validateLength(typeStr, "type", 1, 10, false));
|
||||||
|
targetName = ValidationUtil.validateLength(targetName, "target", 1, 50, false);
|
||||||
|
|
||||||
// Validate the target user
|
// Search user or group
|
||||||
UserDao userDao = new UserDao();
|
String targetId = null;
|
||||||
User user = userDao.getActiveByUsername(username);
|
switch (type) {
|
||||||
if (user == null) {
|
case USER:
|
||||||
throw new ClientException("UserNotFound", MessageFormat.format("User not found: {0}", username));
|
UserDao userDao = new UserDao();
|
||||||
|
User user = userDao.getActiveByUsername(targetName);
|
||||||
|
if (user != null) {
|
||||||
|
targetId = user.getId();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GROUP:
|
||||||
|
GroupDao groupDao = new GroupDao();
|
||||||
|
Group group = groupDao.getActiveByName(targetName);
|
||||||
|
if (group != null) {
|
||||||
|
targetId = group.getId();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SHARE:
|
||||||
|
// Share must use the Share REST resource
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does a target has been found?
|
||||||
|
if (targetId == null) {
|
||||||
|
throw new ClientException("InvalidTarget", MessageFormat.format("This target does not exist: {0}", targetName));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check permission on the source by the principal
|
// Check permission on the source by the principal
|
||||||
@ -75,7 +103,7 @@ public class AclResource extends BaseResource {
|
|||||||
Acl acl = new Acl();
|
Acl acl = new Acl();
|
||||||
acl.setSourceId(sourceId);
|
acl.setSourceId(sourceId);
|
||||||
acl.setPerm(perm);
|
acl.setPerm(perm);
|
||||||
acl.setTargetId(user.getId());
|
acl.setTargetId(targetId);
|
||||||
|
|
||||||
// Avoid duplicates
|
// Avoid duplicates
|
||||||
if (!aclDao.checkPermission(acl.getSourceId(), acl.getPerm(), Lists.newArrayList(acl.getTargetId()))) {
|
if (!aclDao.checkPermission(acl.getSourceId(), acl.getPerm(), Lists.newArrayList(acl.getTargetId()))) {
|
||||||
@ -85,8 +113,8 @@ public class AclResource extends BaseResource {
|
|||||||
JsonObjectBuilder response = Json.createObjectBuilder()
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
.add("perm", acl.getPerm().name())
|
.add("perm", acl.getPerm().name())
|
||||||
.add("id", acl.getTargetId())
|
.add("id", acl.getTargetId())
|
||||||
.add("name", user.getUsername())
|
.add("name", targetName)
|
||||||
.add("type", AclTargetType.USER.name());
|
.add("type", type.name());
|
||||||
return Response.ok().entity(response.build()).build();
|
return Response.ok().entity(response.build()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +124,9 @@ public class AclResource extends BaseResource {
|
|||||||
/**
|
/**
|
||||||
* Deletes an ACL.
|
* Deletes an ACL.
|
||||||
*
|
*
|
||||||
* @param id ACL ID
|
* @param sourceId Source ID
|
||||||
|
* @param permStr Permission
|
||||||
|
* @param targetId Target ID
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
@DELETE
|
@DELETE
|
||||||
@ -155,20 +185,25 @@ public class AclResource extends BaseResource {
|
|||||||
// Search users
|
// Search users
|
||||||
UserDao userDao = new UserDao();
|
UserDao userDao = new UserDao();
|
||||||
JsonArrayBuilder users = Json.createArrayBuilder();
|
JsonArrayBuilder users = Json.createArrayBuilder();
|
||||||
|
|
||||||
PaginatedList<UserDto> paginatedList = PaginatedLists.create();
|
|
||||||
SortCriteria sortCriteria = new SortCriteria(1, true);
|
SortCriteria sortCriteria = new SortCriteria(1, true);
|
||||||
|
List<UserDto> userDtoList = userDao.findByCriteria(new UserCriteria().setSearch(search), sortCriteria);
|
||||||
userDao.findByCriteria(paginatedList, new UserCriteria().setSearch(search), sortCriteria);
|
for (UserDto userDto : userDtoList) {
|
||||||
for (UserDto userDto : paginatedList.getResultList()) {
|
|
||||||
users.add(Json.createObjectBuilder()
|
users.add(Json.createObjectBuilder()
|
||||||
.add("username", userDto.getUsername()));
|
.add("name", userDto.getUsername()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Returns groups too
|
// Search groups
|
||||||
|
GroupDao groupDao = new GroupDao();
|
||||||
|
JsonArrayBuilder groups = Json.createArrayBuilder();
|
||||||
|
List<GroupDto> groupDtoList = groupDao.findByCriteria(new GroupCriteria().setSearch(search), sortCriteria);
|
||||||
|
for (GroupDto groupDto : groupDtoList) {
|
||||||
|
groups.add(Json.createObjectBuilder()
|
||||||
|
.add("name", groupDto.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
JsonObjectBuilder response = Json.createObjectBuilder()
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
.add("users", users);
|
.add("users", users)
|
||||||
|
.add("groups", groups);
|
||||||
return Response.ok().entity(response.build()).build();
|
return Response.ok().entity(response.build()).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ public abstract class BaseResource {
|
|||||||
* @return List of ACL target ID
|
* @return List of ACL target ID
|
||||||
*/
|
*/
|
||||||
protected List<String> getTargetIdList(String shareId) {
|
protected List<String> getTargetIdList(String shareId) {
|
||||||
List<String> targetIdList = Lists.newArrayList(principal.getGroupIdList());
|
List<String> targetIdList = Lists.newArrayList(principal.getGroupIdSet());
|
||||||
if (principal.getId() != null) {
|
if (principal.getId() != null) {
|
||||||
targetIdList.add(principal.getId());
|
targetIdList.add(principal.getId());
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ public class DocumentResource extends BaseResource {
|
|||||||
|
|
||||||
if (!principal.isAnonymous()
|
if (!principal.isAnonymous()
|
||||||
&& (aclDto.getTargetId().equals(principal.getId())
|
&& (aclDto.getTargetId().equals(principal.getId())
|
||||||
|| principal.getGroupIdList().contains(aclDto.getTargetId()))
|
|| principal.getGroupIdSet().contains(aclDto.getTargetId()))
|
||||||
&& aclDto.getPerm() == PermType.WRITE) {
|
&& aclDto.getPerm() == PermType.WRITE) {
|
||||||
// The document is writable for the current user
|
// The document is writable for the current user
|
||||||
writable = true;
|
writable = true;
|
||||||
|
@ -1,17 +1,26 @@
|
|||||||
package com.sismics.docs.rest.resource;
|
package com.sismics.docs.rest.resource;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.json.Json;
|
import javax.json.Json;
|
||||||
import javax.json.JsonObjectBuilder;
|
import javax.json.JsonObjectBuilder;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.FormParam;
|
import javax.ws.rs.FormParam;
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.sismics.docs.core.dao.jpa.GroupDao;
|
import com.sismics.docs.core.dao.jpa.GroupDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.UserDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.criteria.GroupCriteria;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.GroupDto;
|
||||||
import com.sismics.docs.core.model.jpa.Group;
|
import com.sismics.docs.core.model.jpa.Group;
|
||||||
|
import com.sismics.docs.core.model.jpa.User;
|
||||||
|
import com.sismics.docs.core.model.jpa.UserGroup;
|
||||||
import com.sismics.docs.rest.constant.BaseFunction;
|
import com.sismics.docs.rest.constant.BaseFunction;
|
||||||
import com.sismics.rest.exception.ClientException;
|
import com.sismics.rest.exception.ClientException;
|
||||||
import com.sismics.rest.exception.ForbiddenClientException;
|
import com.sismics.rest.exception.ForbiddenClientException;
|
||||||
@ -39,10 +48,11 @@ public class GroupResource extends BaseResource {
|
|||||||
|
|
||||||
// Validate input
|
// Validate input
|
||||||
name = ValidationUtil.validateLength(name, "name", 1, 50, false);
|
name = ValidationUtil.validateLength(name, "name", 1, 50, false);
|
||||||
|
ValidationUtil.validateAlphanumeric(name, "name");
|
||||||
|
|
||||||
// Avoid duplicates
|
// Avoid duplicates
|
||||||
GroupDao groupDao = new GroupDao();
|
GroupDao groupDao = new GroupDao();
|
||||||
Group existingGroup = groupDao.getByName(name);
|
Group existingGroup = groupDao.getActiveByName(name);
|
||||||
if (existingGroup != null) {
|
if (existingGroup != null) {
|
||||||
throw new ClientException("GroupAlreadyExists", MessageFormat.format("This group already exists: {0}", name));
|
throw new ClientException("GroupAlreadyExists", MessageFormat.format("This group already exists: {0}", name));
|
||||||
}
|
}
|
||||||
@ -50,9 +60,9 @@ public class GroupResource extends BaseResource {
|
|||||||
// Validate parent
|
// Validate parent
|
||||||
String parentId = null;
|
String parentId = null;
|
||||||
if (!Strings.isNullOrEmpty(parentName)) {
|
if (!Strings.isNullOrEmpty(parentName)) {
|
||||||
Group parentGroup = groupDao.getByName(parentName);
|
Group parentGroup = groupDao.getActiveByName(parentName);
|
||||||
if (parentGroup == null) {
|
if (parentGroup == null) {
|
||||||
throw new ClientException("ParentGroupNotFound", MessageFormat.format("This group doest not exists: {0}", parentName));
|
throw new ClientException("ParentGroupNotFound", MessageFormat.format("This group does not exists: {0}", parentName));
|
||||||
}
|
}
|
||||||
parentId = parentGroup.getId();
|
parentId = parentGroup.getId();
|
||||||
}
|
}
|
||||||
@ -67,4 +77,104 @@ public class GroupResource extends BaseResource {
|
|||||||
.add("status", "ok");
|
.add("status", "ok");
|
||||||
return Response.ok().entity(response.build()).build();
|
return Response.ok().entity(response.build()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a user to a group.
|
||||||
|
*
|
||||||
|
* @param groupName Group name
|
||||||
|
* @param username Username
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
@PUT
|
||||||
|
@Path("{groupName: [a-zA-Z0-9_]+}")
|
||||||
|
public Response addMember(@PathParam("groupName") String groupName,
|
||||||
|
@FormParam("username") String username) {
|
||||||
|
if (!authenticate()) {
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
checkBaseFunction(BaseFunction.ADMIN);
|
||||||
|
|
||||||
|
// Validate input
|
||||||
|
groupName = ValidationUtil.validateLength(groupName, "name", 1, 50, false);
|
||||||
|
username = ValidationUtil.validateLength(username, "username", 1, 50, false);
|
||||||
|
|
||||||
|
// Get the group
|
||||||
|
GroupDao groupDao = new GroupDao();
|
||||||
|
Group group = groupDao.getActiveByName(groupName);
|
||||||
|
if (group == null) {
|
||||||
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the user
|
||||||
|
UserDao userDao = new UserDao();
|
||||||
|
User user = userDao.getActiveByUsername(username);
|
||||||
|
if (user == null) {
|
||||||
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid duplicates
|
||||||
|
List<GroupDto> groupDtoList = groupDao.findByCriteria(new GroupCriteria().setUserId(user.getId()), null);
|
||||||
|
boolean found = false;
|
||||||
|
for (GroupDto groupDto : groupDtoList) {
|
||||||
|
if (groupDto.getId().equals(group.getId())) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
// Add the membership
|
||||||
|
UserGroup userGroup = new UserGroup();
|
||||||
|
userGroup.setGroupId(group.getId());
|
||||||
|
userGroup.setUserId(user.getId());
|
||||||
|
groupDao.addMember(userGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always return OK
|
||||||
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
|
.add("status", "ok");
|
||||||
|
return Response.ok().entity(response.build()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an user from a group.
|
||||||
|
*
|
||||||
|
* @param groupName Group name
|
||||||
|
* @param username Username
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
@Path("{groupName: [a-zA-Z0-9_]+}/{username: [a-zA-Z0-9_]+}")
|
||||||
|
public Response removeMember(@PathParam("groupName") String groupName,
|
||||||
|
@PathParam("username") String username) {
|
||||||
|
if (!authenticate()) {
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
checkBaseFunction(BaseFunction.ADMIN);
|
||||||
|
|
||||||
|
// Validate input
|
||||||
|
groupName = ValidationUtil.validateLength(groupName, "name", 1, 50, false);
|
||||||
|
username = ValidationUtil.validateLength(username, "username", 1, 50, false);
|
||||||
|
|
||||||
|
// Get the group
|
||||||
|
GroupDao groupDao = new GroupDao();
|
||||||
|
Group group = groupDao.getActiveByName(groupName);
|
||||||
|
if (group == null) {
|
||||||
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the user
|
||||||
|
UserDao userDao = new UserDao();
|
||||||
|
User user = userDao.getActiveByUsername(username);
|
||||||
|
if (user == null) {
|
||||||
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the membership
|
||||||
|
groupDao.removeMember(group.getId(), user.getId());
|
||||||
|
|
||||||
|
// Always return OK
|
||||||
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
|
.add("status", "ok");
|
||||||
|
return Response.ok().entity(response.build()).build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ public class ShareResource extends BaseResource {
|
|||||||
* Add a share to a document.
|
* Add a share to a document.
|
||||||
*
|
*
|
||||||
* @param documentId Document ID
|
* @param documentId Document ID
|
||||||
|
* @param name Share name
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
@PUT
|
@PUT
|
||||||
|
@ -29,9 +29,12 @@ import com.sismics.docs.core.constant.Constants;
|
|||||||
import com.sismics.docs.core.dao.jpa.AuthenticationTokenDao;
|
import com.sismics.docs.core.dao.jpa.AuthenticationTokenDao;
|
||||||
import com.sismics.docs.core.dao.jpa.DocumentDao;
|
import com.sismics.docs.core.dao.jpa.DocumentDao;
|
||||||
import com.sismics.docs.core.dao.jpa.FileDao;
|
import com.sismics.docs.core.dao.jpa.FileDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.GroupDao;
|
||||||
import com.sismics.docs.core.dao.jpa.RoleBaseFunctionDao;
|
import com.sismics.docs.core.dao.jpa.RoleBaseFunctionDao;
|
||||||
import com.sismics.docs.core.dao.jpa.UserDao;
|
import com.sismics.docs.core.dao.jpa.UserDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.criteria.GroupCriteria;
|
||||||
import com.sismics.docs.core.dao.jpa.criteria.UserCriteria;
|
import com.sismics.docs.core.dao.jpa.criteria.UserCriteria;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.GroupDto;
|
||||||
import com.sismics.docs.core.dao.jpa.dto.UserDto;
|
import com.sismics.docs.core.dao.jpa.dto.UserDto;
|
||||||
import com.sismics.docs.core.event.DocumentDeletedAsyncEvent;
|
import com.sismics.docs.core.event.DocumentDeletedAsyncEvent;
|
||||||
import com.sismics.docs.core.event.FileDeletedAsyncEvent;
|
import com.sismics.docs.core.event.FileDeletedAsyncEvent;
|
||||||
@ -41,8 +44,6 @@ import com.sismics.docs.core.model.jpa.Document;
|
|||||||
import com.sismics.docs.core.model.jpa.File;
|
import com.sismics.docs.core.model.jpa.File;
|
||||||
import com.sismics.docs.core.model.jpa.User;
|
import com.sismics.docs.core.model.jpa.User;
|
||||||
import com.sismics.docs.core.util.EncryptionUtil;
|
import com.sismics.docs.core.util.EncryptionUtil;
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedList;
|
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
|
||||||
import com.sismics.docs.core.util.jpa.SortCriteria;
|
import com.sismics.docs.core.util.jpa.SortCriteria;
|
||||||
import com.sismics.docs.rest.constant.BaseFunction;
|
import com.sismics.docs.rest.constant.BaseFunction;
|
||||||
import com.sismics.rest.exception.ClientException;
|
import com.sismics.rest.exception.ClientException;
|
||||||
@ -299,14 +300,7 @@ public class UserResource extends BaseResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the value of the session token
|
// Get the value of the session token
|
||||||
String authToken = null;
|
String authToken = getAuthToken();
|
||||||
if (request.getCookies() != null) {
|
|
||||||
for (Cookie cookie : request.getCookies()) {
|
|
||||||
if (TokenBasedSecurityFilter.COOKIE_NAME.equals(cookie.getName())) {
|
|
||||||
authToken = cookie.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AuthenticationTokenDao authenticationTokenDao = new AuthenticationTokenDao();
|
AuthenticationTokenDao authenticationTokenDao = new AuthenticationTokenDao();
|
||||||
AuthenticationToken authenticationToken = null;
|
AuthenticationToken authenticationToken = null;
|
||||||
@ -457,18 +451,39 @@ public class UserResource extends BaseResource {
|
|||||||
response.add("is_default_password", Constants.DEFAULT_ADMIN_PASSWORD.equals(adminUser.getPassword()));
|
response.add("is_default_password", Constants.DEFAULT_ADMIN_PASSWORD.equals(adminUser.getPassword()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Update the last connection date
|
||||||
|
String authToken = getAuthToken();
|
||||||
|
AuthenticationTokenDao authenticationTokenDao = new AuthenticationTokenDao();
|
||||||
|
authenticationTokenDao.updateLastConnectionDate(authToken);
|
||||||
|
|
||||||
|
// Build the response
|
||||||
response.add("anonymous", false);
|
response.add("anonymous", false);
|
||||||
UserDao userDao = new UserDao();
|
UserDao userDao = new UserDao();
|
||||||
|
GroupDao groupDao = new GroupDao();
|
||||||
User user = userDao.getById(principal.getId());
|
User user = userDao.getById(principal.getId());
|
||||||
|
List<GroupDto> groupDtoList = groupDao.findByCriteria(new GroupCriteria()
|
||||||
|
.setUserId(user.getId())
|
||||||
|
.setRecursive(true), null);
|
||||||
|
|
||||||
response.add("username", user.getUsername())
|
response.add("username", user.getUsername())
|
||||||
.add("email", user.getEmail())
|
.add("email", user.getEmail())
|
||||||
.add("storage_quota", user.getStorageQuota())
|
.add("storage_quota", user.getStorageQuota())
|
||||||
.add("storage_current", user.getStorageCurrent());
|
.add("storage_current", user.getStorageCurrent());
|
||||||
|
|
||||||
|
// Base functions
|
||||||
JsonArrayBuilder baseFunctions = Json.createArrayBuilder();
|
JsonArrayBuilder baseFunctions = Json.createArrayBuilder();
|
||||||
for (String baseFunction : ((UserPrincipal) principal).getBaseFunctionSet()) {
|
for (String baseFunction : ((UserPrincipal) principal).getBaseFunctionSet()) {
|
||||||
baseFunctions.add(baseFunction);
|
baseFunctions.add(baseFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Groups
|
||||||
|
JsonArrayBuilder groups = Json.createArrayBuilder();
|
||||||
|
for (GroupDto groupDto : groupDtoList) {
|
||||||
|
groups.add(groupDto.getName());
|
||||||
|
}
|
||||||
|
|
||||||
response.add("base_functions", baseFunctions)
|
response.add("base_functions", baseFunctions)
|
||||||
|
.add("groups", groups)
|
||||||
.add("is_default_password", hasBaseFunction(BaseFunction.ADMIN) && Constants.DEFAULT_ADMIN_PASSWORD.equals(user.getPassword()));
|
.add("is_default_password", hasBaseFunction(BaseFunction.ADMIN) && Constants.DEFAULT_ADMIN_PASSWORD.equals(user.getPassword()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,8 +510,19 @@ public class UserResource extends BaseResource {
|
|||||||
throw new ClientException("UserNotFound", "The user doesn't exist");
|
throw new ClientException("UserNotFound", "The user doesn't exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Groups
|
||||||
|
GroupDao groupDao = new GroupDao();
|
||||||
|
List<GroupDto> groupDtoList = groupDao.findByCriteria(
|
||||||
|
new GroupCriteria().setUserId(user.getId()),
|
||||||
|
new SortCriteria(1, true));
|
||||||
|
JsonArrayBuilder groups = Json.createArrayBuilder();
|
||||||
|
for (GroupDto groupDto : groupDtoList) {
|
||||||
|
groups.add(groupDto.getName());
|
||||||
|
}
|
||||||
|
|
||||||
JsonObjectBuilder response = Json.createObjectBuilder()
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
.add("username", user.getUsername())
|
.add("username", user.getUsername())
|
||||||
|
.add("groups", groups)
|
||||||
.add("email", user.getEmail())
|
.add("email", user.getEmail())
|
||||||
.add("storage_quota", user.getStorageQuota())
|
.add("storage_quota", user.getStorageQuota())
|
||||||
.add("storage_current", user.getStorageCurrent());
|
.add("storage_current", user.getStorageCurrent());
|
||||||
@ -515,8 +541,6 @@ public class UserResource extends BaseResource {
|
|||||||
@GET
|
@GET
|
||||||
@Path("list")
|
@Path("list")
|
||||||
public Response list(
|
public Response list(
|
||||||
@QueryParam("limit") Integer limit,
|
|
||||||
@QueryParam("offset") Integer offset,
|
|
||||||
@QueryParam("sort_column") Integer sortColumn,
|
@QueryParam("sort_column") Integer sortColumn,
|
||||||
@QueryParam("asc") Boolean asc) {
|
@QueryParam("asc") Boolean asc) {
|
||||||
if (!authenticate()) {
|
if (!authenticate()) {
|
||||||
@ -524,12 +548,11 @@ public class UserResource extends BaseResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JsonArrayBuilder users = Json.createArrayBuilder();
|
JsonArrayBuilder users = Json.createArrayBuilder();
|
||||||
PaginatedList<UserDto> paginatedList = PaginatedLists.create(limit, offset);
|
|
||||||
SortCriteria sortCriteria = new SortCriteria(sortColumn, asc);
|
SortCriteria sortCriteria = new SortCriteria(sortColumn, asc);
|
||||||
|
|
||||||
UserDao userDao = new UserDao();
|
UserDao userDao = new UserDao();
|
||||||
userDao.findByCriteria(paginatedList, new UserCriteria(), sortCriteria);
|
List<UserDto> userDtoList = userDao.findByCriteria(new UserCriteria(), sortCriteria);
|
||||||
for (UserDto userDto : paginatedList.getResultList()) {
|
for (UserDto userDto : userDtoList) {
|
||||||
users.add(Json.createObjectBuilder()
|
users.add(Json.createObjectBuilder()
|
||||||
.add("id", userDto.getId())
|
.add("id", userDto.getId())
|
||||||
.add("username", userDto.getUsername())
|
.add("username", userDto.getUsername())
|
||||||
@ -540,7 +563,6 @@ public class UserResource extends BaseResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JsonObjectBuilder response = Json.createObjectBuilder()
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
.add("total", paginatedList.getResultCount())
|
|
||||||
.add("users", users);
|
.add("users", users);
|
||||||
return Response.ok().entity(response.build()).build();
|
return Response.ok().entity(response.build()).build();
|
||||||
}
|
}
|
||||||
@ -558,14 +580,7 @@ public class UserResource extends BaseResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the value of the session token
|
// Get the value of the session token
|
||||||
String authToken = null;
|
String authToken = getAuthToken();
|
||||||
if (request.getCookies() != null) {
|
|
||||||
for (Cookie cookie : request.getCookies()) {
|
|
||||||
if (TokenBasedSecurityFilter.COOKIE_NAME.equals(cookie.getName())) {
|
|
||||||
authToken = cookie.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonArrayBuilder sessions = Json.createArrayBuilder();
|
JsonArrayBuilder sessions = Json.createArrayBuilder();
|
||||||
AuthenticationTokenDao authenticationTokenDao = new AuthenticationTokenDao();
|
AuthenticationTokenDao authenticationTokenDao = new AuthenticationTokenDao();
|
||||||
@ -600,14 +615,7 @@ public class UserResource extends BaseResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the value of the session token
|
// Get the value of the session token
|
||||||
String authToken = null;
|
String authToken = getAuthToken();
|
||||||
if (request.getCookies() != null) {
|
|
||||||
for (Cookie cookie : request.getCookies()) {
|
|
||||||
if (TokenBasedSecurityFilter.COOKIE_NAME.equals(cookie.getName())) {
|
|
||||||
authToken = cookie.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove other tokens
|
// Remove other tokens
|
||||||
AuthenticationTokenDao authenticationTokenDao = new AuthenticationTokenDao();
|
AuthenticationTokenDao authenticationTokenDao = new AuthenticationTokenDao();
|
||||||
@ -618,4 +626,20 @@ public class UserResource extends BaseResource {
|
|||||||
.add("status", "ok");
|
.add("status", "ok");
|
||||||
return Response.ok().entity(response.build()).build();
|
return Response.ok().entity(response.build()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the authentication token value.
|
||||||
|
*
|
||||||
|
* @return Token value
|
||||||
|
*/
|
||||||
|
private String getAuthToken() {
|
||||||
|
if (request.getCookies() != null) {
|
||||||
|
for (Cookie cookie : request.getCookies()) {
|
||||||
|
if (TokenBasedSecurityFilter.COOKIE_NAME.equals(cookie.getName())) {
|
||||||
|
return cookie.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ angular.module('docs').controller('DocumentViewPermissions', function ($scope, $
|
|||||||
.get({
|
.get({
|
||||||
search: $viewValue
|
search: $viewValue
|
||||||
}).then(function(data) {
|
}).then(function(data) {
|
||||||
deferred.resolve(_.pluck(data.users, 'username'), true);
|
deferred.resolve(_.pluck(data.users, 'name'), true);
|
||||||
});
|
});
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ angular.module('docs').controller('SettingsUser', function($scope, $state, Resta
|
|||||||
* Load users from server.
|
* Load users from server.
|
||||||
*/
|
*/
|
||||||
$scope.loadUsers = function() {
|
$scope.loadUsers = function() {
|
||||||
Restangular.one('user/list').get({ limit: 100 }).then(function(data) {
|
Restangular.one('user/list').get().then(function(data) {
|
||||||
$scope.users = data.users;
|
$scope.users = data.users;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -22,10 +22,10 @@
|
|||||||
|
|
||||||
<form name="aclForm" class="form-horizontal">
|
<form name="aclForm" class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class=" col-sm-2 control-label" for="inputTarget">User</label>
|
<label class=" col-sm-2 control-label" for="inputTarget">For</label>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
<input required ng-maxlength="50" class="form-control" type="text" id="inputTarget"
|
<input required ng-maxlength="50" class="form-control" type="text" id="inputTarget"
|
||||||
placeholder="Type a username" name="username" ng-model="acl.username" autocomplete="off"
|
placeholder="Type a username" name="username" ng-model="acl.target" autocomplete="off"
|
||||||
typeahead="username for username in getTargetAclTypeahead($viewValue) | filter: $viewValue"
|
typeahead="username for username in getTargetAclTypeahead($viewValue) | filter: $viewValue"
|
||||||
typeahead-wait-ms="200" />
|
typeahead-wait-ms="200" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -28,15 +28,18 @@ public class TestAclResource extends BaseJerseyTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testAclResource() {
|
public void testAclResource() {
|
||||||
|
// Create aclGroup2
|
||||||
|
clientUtil.createGroup("aclGroup2");
|
||||||
|
|
||||||
// Login acl1
|
// Login acl1
|
||||||
clientUtil.createUser("acl1");
|
clientUtil.createUser("acl1");
|
||||||
String acl1Token = clientUtil.login("acl1");
|
String acl1Token = clientUtil.login("acl1");
|
||||||
|
|
||||||
// Login acl2
|
// Login acl2
|
||||||
clientUtil.createUser("acl2");
|
clientUtil.createUser("acl2", "aclGroup2");
|
||||||
String acl2Token = clientUtil.login("acl2");
|
String acl2Token = clientUtil.login("acl2");
|
||||||
|
|
||||||
// Create a document
|
// Create a document with acl1
|
||||||
JsonObject json = target().path("/document").request()
|
JsonObject json = target().path("/document").request()
|
||||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
|
||||||
.put(Entity.form(new Form()
|
.put(Entity.form(new Form()
|
||||||
@ -65,7 +68,8 @@ public class TestAclResource extends BaseJerseyTest {
|
|||||||
.put(Entity.form(new Form()
|
.put(Entity.form(new Form()
|
||||||
.param("source", document1Id)
|
.param("source", document1Id)
|
||||||
.param("perm", "READ")
|
.param("perm", "READ")
|
||||||
.param("username", "acl2")), JsonObject.class);
|
.param("target", "acl2")
|
||||||
|
.param("type", "USER")), JsonObject.class);
|
||||||
String acl2Id = json.getString("id");
|
String acl2Id = json.getString("id");
|
||||||
|
|
||||||
// Add an ACL WRITE for acl2 with acl1
|
// Add an ACL WRITE for acl2 with acl1
|
||||||
@ -74,7 +78,8 @@ public class TestAclResource extends BaseJerseyTest {
|
|||||||
.put(Entity.form(new Form()
|
.put(Entity.form(new Form()
|
||||||
.param("source", document1Id)
|
.param("source", document1Id)
|
||||||
.param("perm", "WRITE")
|
.param("perm", "WRITE")
|
||||||
.param("username", "acl2")), JsonObject.class);
|
.param("target", "acl2")
|
||||||
|
.param("type", "USER")), JsonObject.class);
|
||||||
|
|
||||||
// Add an ACL WRITE for acl2 with acl1 (again)
|
// Add an ACL WRITE for acl2 with acl1 (again)
|
||||||
json = target().path("/acl").request()
|
json = target().path("/acl").request()
|
||||||
@ -82,7 +87,27 @@ public class TestAclResource extends BaseJerseyTest {
|
|||||||
.put(Entity.form(new Form()
|
.put(Entity.form(new Form()
|
||||||
.param("source", document1Id)
|
.param("source", document1Id)
|
||||||
.param("perm", "WRITE")
|
.param("perm", "WRITE")
|
||||||
.param("username", "acl2")), JsonObject.class);
|
.param("target", "acl2")
|
||||||
|
.param("type", "USER")), JsonObject.class);
|
||||||
|
|
||||||
|
// Add an ACL READ for aclGroup2 with acl1
|
||||||
|
json = target().path("/acl").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("source", document1Id)
|
||||||
|
.param("perm", "READ")
|
||||||
|
.param("target", "aclGroup2")
|
||||||
|
.param("type", "GROUP")), JsonObject.class);
|
||||||
|
String aclGroup2Id = json.getString("id");
|
||||||
|
|
||||||
|
// Add an ACL WRITE for aclGroup2 with acl1
|
||||||
|
json = target().path("/acl").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("source", document1Id)
|
||||||
|
.param("perm", "WRITE")
|
||||||
|
.param("target", "aclGroup2")
|
||||||
|
.param("type", "GROUP")), JsonObject.class);
|
||||||
|
|
||||||
// Get the document as acl1
|
// Get the document as acl1
|
||||||
json = target().path("/document/" + document1Id).request()
|
json = target().path("/document/" + document1Id).request()
|
||||||
@ -90,7 +115,8 @@ public class TestAclResource extends BaseJerseyTest {
|
|||||||
.get(JsonObject.class);
|
.get(JsonObject.class);
|
||||||
Assert.assertEquals(document1Id, json.getString("id"));
|
Assert.assertEquals(document1Id, json.getString("id"));
|
||||||
acls = json.getJsonArray("acls");
|
acls = json.getJsonArray("acls");
|
||||||
Assert.assertEquals(4, acls.size());
|
Assert.assertEquals(6, acls.size());
|
||||||
|
Assert.assertTrue(json.getBoolean("writable"));
|
||||||
|
|
||||||
// Get the document as acl2
|
// Get the document as acl2
|
||||||
json = target().path("/document/" + document1Id).request()
|
json = target().path("/document/" + document1Id).request()
|
||||||
@ -98,7 +124,8 @@ public class TestAclResource extends BaseJerseyTest {
|
|||||||
.get(JsonObject.class);
|
.get(JsonObject.class);
|
||||||
Assert.assertEquals(document1Id, json.getString("id"));
|
Assert.assertEquals(document1Id, json.getString("id"));
|
||||||
acls = json.getJsonArray("acls");
|
acls = json.getJsonArray("acls");
|
||||||
Assert.assertEquals(4, acls.size());
|
Assert.assertEquals(6, acls.size());
|
||||||
|
Assert.assertTrue(json.getBoolean("writable"));
|
||||||
|
|
||||||
// Update the document as acl2
|
// Update the document as acl2
|
||||||
json = target().path("/document/" + document1Id).request()
|
json = target().path("/document/" + document1Id).request()
|
||||||
@ -121,6 +148,29 @@ public class TestAclResource extends BaseJerseyTest {
|
|||||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
||||||
.delete(JsonObject.class);
|
.delete(JsonObject.class);
|
||||||
|
|
||||||
|
// Get the document as acl2
|
||||||
|
json = target().path("/document/" + document1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
Assert.assertEquals(document1Id, json.getString("id"));
|
||||||
|
acls = json.getJsonArray("acls");
|
||||||
|
Assert.assertEquals(5, acls.size());
|
||||||
|
Assert.assertTrue(json.getBoolean("writable")); // Writable by aclGroup2
|
||||||
|
|
||||||
|
// Delete the ACL WRITE for aclGroup2 with acl2
|
||||||
|
target().path("/acl/" + document1Id + "/WRITE/" + aclGroup2Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
||||||
|
.delete(JsonObject.class);
|
||||||
|
|
||||||
|
// Get the document as acl2
|
||||||
|
json = target().path("/document/" + document1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
Assert.assertEquals(document1Id, json.getString("id"));
|
||||||
|
acls = json.getJsonArray("acls");
|
||||||
|
Assert.assertEquals(4, acls.size());
|
||||||
|
Assert.assertFalse(json.getBoolean("writable"));
|
||||||
|
|
||||||
// Delete the ACL READ for acl2 with acl2 (not authorized)
|
// Delete the ACL READ for acl2 with acl2 (not authorized)
|
||||||
response = target().path("/acl/" + document1Id + "/READ/" + acl2Id).request()
|
response = target().path("/acl/" + document1Id + "/READ/" + acl2Id).request()
|
||||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
||||||
@ -132,6 +182,16 @@ public class TestAclResource extends BaseJerseyTest {
|
|||||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
|
||||||
.delete(JsonObject.class);
|
.delete(JsonObject.class);
|
||||||
|
|
||||||
|
// Get the document as acl2 (visible by group)
|
||||||
|
target().path("/document/" + document1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
|
||||||
|
// Delete the ACL READ for aclGroup2 with acl1
|
||||||
|
target().path("/acl/" + document1Id + "/READ/" + aclGroup2Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
|
||||||
|
.delete(JsonObject.class);
|
||||||
|
|
||||||
// Get the document as acl1
|
// Get the document as acl1
|
||||||
json = target().path("/document/" + document1Id).request()
|
json = target().path("/document/" + document1Id).request()
|
||||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
|
||||||
@ -167,5 +227,7 @@ public class TestAclResource extends BaseJerseyTest {
|
|||||||
.get(JsonObject.class);
|
.get(JsonObject.class);
|
||||||
JsonArray users = json.getJsonArray("users");
|
JsonArray users = json.getJsonArray("users");
|
||||||
Assert.assertEquals(2, users.size());
|
Assert.assertEquals(2, users.size());
|
||||||
|
JsonArray groups = json.getJsonArray("groups");
|
||||||
|
Assert.assertEquals(1, groups.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,14 @@
|
|||||||
package com.sismics.docs.rest;
|
package com.sismics.docs.rest;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.json.JsonArray;
|
||||||
import javax.json.JsonObject;
|
import javax.json.JsonObject;
|
||||||
import javax.ws.rs.client.Entity;
|
import javax.ws.rs.client.Entity;
|
||||||
import javax.ws.rs.core.Form;
|
import javax.ws.rs.core.Form;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
||||||
@ -25,10 +30,71 @@ public class TestGroupResource extends BaseJerseyTest {
|
|||||||
// Login admin
|
// Login admin
|
||||||
String adminToken = clientUtil.login("admin", "admin", false);
|
String adminToken = clientUtil.login("admin", "admin", false);
|
||||||
|
|
||||||
// Create a group
|
// Create group hierarchy
|
||||||
target().path("/group").request()
|
clientUtil.createGroup("g1");
|
||||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
clientUtil.createGroup("g11", "g1");
|
||||||
.put(Entity.form(new Form()
|
clientUtil.createGroup("g12", "g1");
|
||||||
.param("name", "Group 1")), JsonObject.class);
|
clientUtil.createGroup("g111", "g11");
|
||||||
|
clientUtil.createGroup("g112", "g11");
|
||||||
|
|
||||||
|
// Login group1
|
||||||
|
clientUtil.createUser("group1", "g112", "g12");
|
||||||
|
String group1Token = clientUtil.login("group1");
|
||||||
|
|
||||||
|
// Check group1 groups (all computed groups)
|
||||||
|
JsonObject json = target().path("/user").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, group1Token)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
JsonArray groups = json.getJsonArray("groups");
|
||||||
|
List<String> groupList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < groups.size(); i++) {
|
||||||
|
groupList.add(groups.getString(i));
|
||||||
|
}
|
||||||
|
Assert.assertEquals(4, groups.size());
|
||||||
|
Assert.assertTrue(groupList.contains("g1"));
|
||||||
|
Assert.assertTrue(groupList.contains("g12"));
|
||||||
|
Assert.assertTrue(groupList.contains("g11"));
|
||||||
|
Assert.assertTrue(groupList.contains("g112"));
|
||||||
|
|
||||||
|
// Check group1 groups with admin (only direct groups)
|
||||||
|
json = target().path("/user/group1").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
groups = json.getJsonArray("groups");
|
||||||
|
Assert.assertEquals(2, groups.size());
|
||||||
|
Assert.assertEquals("g112", groups.getString(0));
|
||||||
|
Assert.assertEquals("g12", groups.getString(1));
|
||||||
|
|
||||||
|
// Add group1 to g112 (again)
|
||||||
|
json = target().path("/group/g112").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("username", "group1")), JsonObject.class);
|
||||||
|
|
||||||
|
// Check group1 groups (all computed groups)
|
||||||
|
json = target().path("/user").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, group1Token)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
groups = json.getJsonArray("groups");
|
||||||
|
Assert.assertEquals(4, groups.size());
|
||||||
|
|
||||||
|
// Remove group1 from g12
|
||||||
|
json = target().path("/group/g12/group1").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.delete(JsonObject.class);
|
||||||
|
|
||||||
|
// Check group1 groups (all computed groups)
|
||||||
|
json = target().path("/user").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, group1Token)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
groups = json.getJsonArray("groups");
|
||||||
|
groupList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < groups.size(); i++) {
|
||||||
|
groupList.add(groups.getString(i));
|
||||||
|
}
|
||||||
|
Assert.assertEquals(3, groups.size());
|
||||||
|
Assert.assertTrue(groupList.contains("g1"));
|
||||||
|
Assert.assertTrue(groupList.contains("g11"));
|
||||||
|
Assert.assertTrue(groupList.contains("g112"));
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user