mirror of
https://github.com/sismics/docs.git
synced 2024-11-22 14:07:55 +01:00
#20: Audit log displayed on main screen
This commit is contained in:
parent
b2a38cea62
commit
ea4e3fd8f2
@ -0,0 +1,23 @@
|
|||||||
|
package com.sismics.docs.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log types.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public enum AuditLogType {
|
||||||
|
/**
|
||||||
|
* Create.
|
||||||
|
*/
|
||||||
|
CREATE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update.
|
||||||
|
*/
|
||||||
|
UPDATE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete.
|
||||||
|
*/
|
||||||
|
DELETE
|
||||||
|
}
|
@ -9,9 +9,11 @@ import javax.persistence.EntityManager;
|
|||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
|
||||||
import com.sismics.docs.core.constant.AclTargetType;
|
import com.sismics.docs.core.constant.AclTargetType;
|
||||||
|
import com.sismics.docs.core.constant.AuditLogType;
|
||||||
import com.sismics.docs.core.constant.PermType;
|
import com.sismics.docs.core.constant.PermType;
|
||||||
import com.sismics.docs.core.dao.jpa.dto.AclDto;
|
import com.sismics.docs.core.dao.jpa.dto.AclDto;
|
||||||
import com.sismics.docs.core.model.jpa.Acl;
|
import com.sismics.docs.core.model.jpa.Acl;
|
||||||
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
import com.sismics.util.context.ThreadLocalContext;
|
import com.sismics.util.context.ThreadLocalContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,6 +37,9 @@ public class AclDao {
|
|||||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
em.persist(acl);
|
em.persist(acl);
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(acl, AuditLogType.CREATE);
|
||||||
|
|
||||||
return acl.getId();
|
return acl.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,9 +126,22 @@ public class AclDao {
|
|||||||
* @param perm Permission
|
* @param perm Permission
|
||||||
* @param targetId Target ID
|
* @param targetId Target ID
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void delete(String sourceId, PermType perm, String targetId) {
|
public void delete(String sourceId, PermType perm, String targetId) {
|
||||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
Query q = em.createQuery("update Acl a set a.deleteDate = :dateNow where a.sourceId = :sourceId and a.perm = :perm and a.targetId = :targetId");
|
|
||||||
|
// Create audit log
|
||||||
|
Query q = em.createQuery("from Acl a where a.sourceId = :sourceId and a.perm = :perm and a.targetId = :targetId");
|
||||||
|
q.setParameter("sourceId", sourceId);
|
||||||
|
q.setParameter("perm", perm);
|
||||||
|
q.setParameter("targetId", targetId);
|
||||||
|
List<Acl> aclList = q.getResultList();
|
||||||
|
for (Acl acl : aclList) {
|
||||||
|
AuditLogUtil.create(acl, AuditLogType.DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Soft delete the ACLs
|
||||||
|
q = em.createQuery("update Acl a set a.deleteDate = :dateNow where a.sourceId = :sourceId and a.perm = :perm and a.targetId = :targetId");
|
||||||
q.setParameter("sourceId", sourceId);
|
q.setParameter("sourceId", sourceId);
|
||||||
q.setParameter("perm", perm);
|
q.setParameter("perm", perm);
|
||||||
q.setParameter("targetId", targetId);
|
q.setParameter("targetId", targetId);
|
||||||
|
@ -0,0 +1,108 @@
|
|||||||
|
package com.sismics.docs.core.dao.jpa;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.sismics.docs.core.constant.AuditLogType;
|
||||||
|
import com.sismics.docs.core.dao.jpa.criteria.AuditLogCriteria;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.AuditLogDto;
|
||||||
|
import com.sismics.docs.core.model.jpa.AuditLog;
|
||||||
|
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.SortCriteria;
|
||||||
|
import com.sismics.util.context.ThreadLocalContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log DAO.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class AuditLogDao {
|
||||||
|
/**
|
||||||
|
* Creates a new audit log.
|
||||||
|
*
|
||||||
|
* @param auditLog Audit log
|
||||||
|
* @return New ID
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public String create(AuditLog auditLog) {
|
||||||
|
// Create the UUID
|
||||||
|
auditLog.setId(UUID.randomUUID().toString());
|
||||||
|
|
||||||
|
// Create the audit log
|
||||||
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
|
auditLog.setCreateDate(new Date());
|
||||||
|
em.persist(auditLog);
|
||||||
|
|
||||||
|
return auditLog.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches audit logs by criteria.
|
||||||
|
*
|
||||||
|
* @param paginatedList List of audit logs (updated by side effects)
|
||||||
|
* @param criteria Search criteria
|
||||||
|
* @param sortCriteria Sort criteria
|
||||||
|
* @return List of audit logs
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void findByCriteria(PaginatedList<AuditLogDto> paginatedList, AuditLogCriteria criteria, SortCriteria sortCriteria) throws Exception {
|
||||||
|
Map<String, Object> parameterMap = new HashMap<String, Object>();
|
||||||
|
List<String> criteriaList = new ArrayList<String>();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder("select l.LOG_ID_C c0, l.LOG_CREATEDATE_D c1, l.LOG_IDENTITY_C c2, l.LOG_CLASSENTITY_C c3, l.LOG_TYPE_C c4, l.LOG_MESSAGE_C c5 ");
|
||||||
|
sb.append(" from T_AUDIT_LOG l ");
|
||||||
|
|
||||||
|
// Adds search criteria
|
||||||
|
if (criteria.getDocumentId() != null) {
|
||||||
|
// ACL on document is not checked here, it's assumed
|
||||||
|
StringBuilder sb0 = new StringBuilder(" (l.LOG_IDENTITY_C = :documentId and l.LOG_CLASSENTITY_C = 'Document' ");
|
||||||
|
sb0.append(" or l.LOG_IDENTITY_C in (select f.FIL_ID_C from T_FILE f where f.FIL_IDDOC_C = :documentId) and l.LOG_CLASSENTITY_C = 'File' ");
|
||||||
|
sb0.append(" or l.LOG_IDENTITY_C in (select a.ACL_ID_C from T_ACL a where a.ACL_SOURCEID_C = :documentId) and l.LOG_CLASSENTITY_C = 'Acl') ");
|
||||||
|
criteriaList.add(sb0.toString());
|
||||||
|
parameterMap.put("documentId", criteria.getDocumentId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (criteria.getUserId() != null) {
|
||||||
|
StringBuilder sb0 = new StringBuilder(" (l.LOG_IDENTITY_C = :userId and l.LOG_CLASSENTITY_C = 'User' ");
|
||||||
|
sb0.append(" or l.LOG_IDENTITY_C in (select t.TAG_ID_C from T_TAG t where t.TAG_IDUSER_C = :userId) and l.LOG_CLASSENTITY_C = 'Tag' ");
|
||||||
|
sb0.append(" or l.LOG_IDENTITY_C in (select d.DOC_ID_C from T_DOCUMENT d where d.DOC_IDUSER_C = :userId) and l.LOG_CLASSENTITY_C = 'Document') ");
|
||||||
|
criteriaList.add(sb0.toString());
|
||||||
|
parameterMap.put("userId", criteria.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!criteriaList.isEmpty()) {
|
||||||
|
sb.append(" where ");
|
||||||
|
sb.append(Joiner.on(" and ").join(criteriaList));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the search
|
||||||
|
QueryParam queryParam = new QueryParam(sb.toString(), parameterMap);
|
||||||
|
List<Object[]> l = PaginatedLists.executePaginatedQuery(paginatedList, queryParam, sortCriteria);
|
||||||
|
|
||||||
|
// Assemble results
|
||||||
|
List<AuditLogDto> auditLogDtoList = new ArrayList<AuditLogDto>();
|
||||||
|
for (Object[] o : l) {
|
||||||
|
int i = 0;
|
||||||
|
AuditLogDto auditLogDto = new AuditLogDto();
|
||||||
|
auditLogDto.setId((String) o[i++]);
|
||||||
|
auditLogDto.setCreateTimestamp(((Timestamp) o[i++]).getTime());
|
||||||
|
auditLogDto.setEntityId((String) o[i++]);
|
||||||
|
auditLogDto.setEntityClass((String) o[i++]);
|
||||||
|
auditLogDto.setType(AuditLogType.valueOf((String) o[i++]));
|
||||||
|
auditLogDto.setMessage((String) o[i++]);
|
||||||
|
auditLogDtoList.add(auditLogDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
paginatedList.setResultList(auditLogDtoList);
|
||||||
|
}
|
||||||
|
}
|
@ -15,11 +15,13 @@ import javax.persistence.Query;
|
|||||||
|
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
import com.sismics.docs.core.constant.AuditLogType;
|
||||||
import com.sismics.docs.core.constant.PermType;
|
import com.sismics.docs.core.constant.PermType;
|
||||||
import com.sismics.docs.core.dao.jpa.criteria.DocumentCriteria;
|
import com.sismics.docs.core.dao.jpa.criteria.DocumentCriteria;
|
||||||
import com.sismics.docs.core.dao.jpa.dto.DocumentDto;
|
import com.sismics.docs.core.dao.jpa.dto.DocumentDto;
|
||||||
import com.sismics.docs.core.dao.lucene.LuceneDao;
|
import com.sismics.docs.core.dao.lucene.LuceneDao;
|
||||||
import com.sismics.docs.core.model.jpa.Document;
|
import com.sismics.docs.core.model.jpa.Document;
|
||||||
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedList;
|
import com.sismics.docs.core.util.jpa.PaginatedList;
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
||||||
import com.sismics.docs.core.util.jpa.QueryParam;
|
import com.sismics.docs.core.util.jpa.QueryParam;
|
||||||
@ -47,6 +49,9 @@ public class DocumentDao {
|
|||||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
em.persist(document);
|
em.persist(document);
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(document, AuditLogType.CREATE);
|
||||||
|
|
||||||
return document.getId();
|
return document.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +150,9 @@ public class DocumentDao {
|
|||||||
q.setParameter("documentId", id);
|
q.setParameter("documentId", id);
|
||||||
q.setParameter("dateNow", dateNow);
|
q.setParameter("dateNow", dateNow);
|
||||||
q.executeUpdate();
|
q.executeUpdate();
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(documentDb, AuditLogType.DELETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,6 +175,7 @@ public class DocumentDao {
|
|||||||
*
|
*
|
||||||
* @param paginatedList List of documents (updated by side effects)
|
* @param paginatedList List of documents (updated by side effects)
|
||||||
* @param criteria Search criteria
|
* @param criteria Search criteria
|
||||||
|
* @param sortCriteria Sort criteria
|
||||||
* @return List of documents
|
* @return List of documents
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@ -248,4 +257,30 @@ public class DocumentDao {
|
|||||||
|
|
||||||
paginatedList.setResultList(documentDtoList);
|
paginatedList.setResultList(documentDtoList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a document.
|
||||||
|
*
|
||||||
|
* @param document Document to update
|
||||||
|
* @return Updated document
|
||||||
|
*/
|
||||||
|
public Document update(Document document) {
|
||||||
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
|
|
||||||
|
// Get the document
|
||||||
|
Query q = em.createQuery("select d from Document d where d.id = :id and d.deleteDate is null");
|
||||||
|
q.setParameter("id", document.getId());
|
||||||
|
Document documentFromDb = (Document) q.getSingleResult();
|
||||||
|
|
||||||
|
// Update the document
|
||||||
|
documentFromDb.setTitle(document.getTitle());
|
||||||
|
documentFromDb.setDescription(document.getDescription());
|
||||||
|
documentFromDb.setCreateDate(document.getCreateDate());
|
||||||
|
documentFromDb.setLanguage(document.getLanguage());
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(documentFromDb, AuditLogType.UPDATE);
|
||||||
|
|
||||||
|
return documentFromDb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,9 @@ import javax.persistence.EntityManager;
|
|||||||
import javax.persistence.NoResultException;
|
import javax.persistence.NoResultException;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
|
||||||
|
import com.sismics.docs.core.constant.AuditLogType;
|
||||||
import com.sismics.docs.core.model.jpa.File;
|
import com.sismics.docs.core.model.jpa.File;
|
||||||
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
import com.sismics.util.context.ThreadLocalContext;
|
import com.sismics.util.context.ThreadLocalContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,6 +35,9 @@ public class FileDao {
|
|||||||
file.setCreateDate(new Date());
|
file.setCreateDate(new Date());
|
||||||
em.persist(file);
|
em.persist(file);
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(file, AuditLogType.CREATE);
|
||||||
|
|
||||||
return file.getId();
|
return file.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +97,9 @@ public class FileDao {
|
|||||||
// Delete the file
|
// Delete the file
|
||||||
Date dateNow = new Date();
|
Date dateNow = new Date();
|
||||||
fileDb.setDeleteDate(dateNow);
|
fileDb.setDeleteDate(dateNow);
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(fileDb, AuditLogType.DELETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,6 +121,9 @@ public class FileDao {
|
|||||||
fileFromDb.setContent(file.getContent());
|
fileFromDb.setContent(file.getContent());
|
||||||
fileFromDb.setOrder(file.getOrder());
|
fileFromDb.setOrder(file.getOrder());
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(fileFromDb, AuditLogType.UPDATE);
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,22 @@
|
|||||||
package com.sismics.docs.core.dao.jpa;
|
package com.sismics.docs.core.dao.jpa;
|
||||||
|
|
||||||
import com.sismics.docs.core.dao.jpa.dto.TagDto;
|
import java.util.ArrayList;
|
||||||
import com.sismics.docs.core.dao.jpa.dto.TagStatDto;
|
import java.util.Date;
|
||||||
import com.sismics.docs.core.model.jpa.DocumentTag;
|
import java.util.List;
|
||||||
import com.sismics.docs.core.model.jpa.Tag;
|
import java.util.Set;
|
||||||
import com.sismics.util.context.ThreadLocalContext;
|
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 java.util.*;
|
|
||||||
|
import com.sismics.docs.core.constant.AuditLogType;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.TagDto;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.TagStatDto;
|
||||||
|
import com.sismics.docs.core.model.jpa.DocumentTag;
|
||||||
|
import com.sismics.docs.core.model.jpa.Tag;
|
||||||
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
|
import com.sismics.util.context.ThreadLocalContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tag DAO.
|
* Tag DAO.
|
||||||
@ -153,6 +160,9 @@ public class TagDao {
|
|||||||
tag.setCreateDate(new Date());
|
tag.setCreateDate(new Date());
|
||||||
em.persist(tag);
|
em.persist(tag);
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(tag, AuditLogType.CREATE);
|
||||||
|
|
||||||
return tag.getId();
|
return tag.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,6 +223,9 @@ public class TagDao {
|
|||||||
q = em.createQuery("delete DocumentTag dt where dt.tagId = :tagId");
|
q = em.createQuery("delete DocumentTag dt where dt.tagId = :tagId");
|
||||||
q.setParameter("tagId", tagId);
|
q.setParameter("tagId", tagId);
|
||||||
q.executeUpdate();
|
q.executeUpdate();
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(tagDb, AuditLogType.DELETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -229,4 +242,28 @@ public class TagDao {
|
|||||||
q.setParameter("name", "%" + name + "%");
|
q.setParameter("name", "%" + name + "%");
|
||||||
return q.getResultList();
|
return q.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a tag.
|
||||||
|
*
|
||||||
|
* @param tag Tag to update
|
||||||
|
* @return Updated tag
|
||||||
|
*/
|
||||||
|
public Tag update(Tag tag) {
|
||||||
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
|
|
||||||
|
// Get the tag
|
||||||
|
Query q = em.createQuery("select t from Tag t where t.id = :id and t.deleteDate is null");
|
||||||
|
q.setParameter("id", tag.getId());
|
||||||
|
Tag tagFromDb = (Tag) q.getSingleResult();
|
||||||
|
|
||||||
|
// Update the tag
|
||||||
|
tagFromDb.setName(tag.getName());
|
||||||
|
tagFromDb.setColor(tag.getColor());
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(tagFromDb, AuditLogType.UPDATE);
|
||||||
|
|
||||||
|
return tagFromDb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,12 @@ import javax.persistence.Query;
|
|||||||
import org.mindrot.jbcrypt.BCrypt;
|
import org.mindrot.jbcrypt.BCrypt;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
|
import com.sismics.docs.core.constant.AuditLogType;
|
||||||
import com.sismics.docs.core.constant.Constants;
|
import com.sismics.docs.core.constant.Constants;
|
||||||
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.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.jpa.PaginatedList;
|
import com.sismics.docs.core.util.jpa.PaginatedList;
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
||||||
import com.sismics.docs.core.util.jpa.QueryParam;
|
import com.sismics.docs.core.util.jpa.QueryParam;
|
||||||
@ -73,11 +75,15 @@ public class UserDao {
|
|||||||
throw new Exception("AlreadyExistingUsername");
|
throw new Exception("AlreadyExistingUsername");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the user
|
||||||
user.setCreateDate(new Date());
|
user.setCreateDate(new Date());
|
||||||
user.setPassword(hashPassword(user.getPassword()));
|
user.setPassword(hashPassword(user.getPassword()));
|
||||||
user.setTheme(Constants.DEFAULT_THEME_ID);
|
user.setTheme(Constants.DEFAULT_THEME_ID);
|
||||||
em.persist(user);
|
em.persist(user);
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(user, AuditLogType.CREATE);
|
||||||
|
|
||||||
return user.getId();
|
return user.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +107,9 @@ public class UserDao {
|
|||||||
userFromDb.setTheme(user.getTheme());
|
userFromDb.setTheme(user.getTheme());
|
||||||
userFromDb.setFirstConnection(user.isFirstConnection());
|
userFromDb.setFirstConnection(user.isFirstConnection());
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(userFromDb, AuditLogType.UPDATE);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,6 +130,9 @@ public class UserDao {
|
|||||||
// Update the user
|
// Update the user
|
||||||
userFromDb.setPassword(hashPassword(user.getPassword()));
|
userFromDb.setPassword(hashPassword(user.getPassword()));
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(userFromDb, AuditLogType.UPDATE);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +206,9 @@ public class UserDao {
|
|||||||
q = em.createQuery("delete from AuthenticationToken at where at.userId = :userId");
|
q = em.createQuery("delete from AuthenticationToken at where at.userId = :userId");
|
||||||
q.setParameter("userId", userFromDb.getId());
|
q.setParameter("userId", userFromDb.getId());
|
||||||
q.executeUpdate();
|
q.executeUpdate();
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(userFromDb, AuditLogType.DELETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.sismics.docs.core.dao.jpa.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log criteria.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class AuditLogCriteria {
|
||||||
|
/**
|
||||||
|
* Document ID.
|
||||||
|
*/
|
||||||
|
private String documentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User ID.
|
||||||
|
*/
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
public String getDocumentId() {
|
||||||
|
return documentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDocumentId(String documentId) {
|
||||||
|
this.documentId = documentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(String userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package com.sismics.docs.core.dao.jpa.dto;
|
||||||
|
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import com.sismics.docs.core.constant.AuditLogType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log DTO.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class AuditLogDto {
|
||||||
|
/**
|
||||||
|
* Audit log ID.
|
||||||
|
*/
|
||||||
|
@Id
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity ID.
|
||||||
|
*/
|
||||||
|
private String entityId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity class.
|
||||||
|
*/
|
||||||
|
private String entityClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log type.
|
||||||
|
*/
|
||||||
|
private AuditLogType type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log message.
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creation date.
|
||||||
|
*/
|
||||||
|
private Long createTimestamp;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEntityId() {
|
||||||
|
return entityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEntityId(String entityId) {
|
||||||
|
this.entityId = entityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEntityClass() {
|
||||||
|
return entityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEntityClass(String entityClass) {
|
||||||
|
this.entityClass = entityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuditLogType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(AuditLogType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCreateTimestamp() {
|
||||||
|
return createTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateTimestamp(Long createTimestamp) {
|
||||||
|
this.createTimestamp = createTimestamp;
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import java.util.Date;
|
|||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EntityListeners;
|
||||||
import javax.persistence.EnumType;
|
import javax.persistence.EnumType;
|
||||||
import javax.persistence.Enumerated;
|
import javax.persistence.Enumerated;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
@ -11,6 +12,7 @@ import javax.persistence.Table;
|
|||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import com.sismics.docs.core.constant.PermType;
|
import com.sismics.docs.core.constant.PermType;
|
||||||
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ACL entity.
|
* ACL entity.
|
||||||
@ -18,8 +20,9 @@ import com.sismics.docs.core.constant.PermType;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@EntityListeners(AuditLogUtil.class)
|
||||||
@Table(name = "T_ACL")
|
@Table(name = "T_ACL")
|
||||||
public class Acl {
|
public class Acl implements Loggable {
|
||||||
/**
|
/**
|
||||||
* ACL ID.
|
* ACL ID.
|
||||||
*/
|
*/
|
||||||
@ -84,6 +87,7 @@ public class Acl {
|
|||||||
this.targetId = targetId;
|
this.targetId = targetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Date getDeleteDate() {
|
public Date getDeleteDate() {
|
||||||
return deleteDate;
|
return deleteDate;
|
||||||
}
|
}
|
||||||
@ -101,4 +105,9 @@ public class Acl {
|
|||||||
.add("targetId", targetId)
|
.add("targetId", targetId)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toMessage() {
|
||||||
|
return perm.name();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,178 @@
|
|||||||
|
package com.sismics.docs.core.model.jpa;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.sismics.docs.core.constant.AuditLogType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "T_AUDIT_LOG")
|
||||||
|
public class AuditLog {
|
||||||
|
/**
|
||||||
|
* Audit log ID.
|
||||||
|
*/
|
||||||
|
@Id
|
||||||
|
@Column(name = "LOG_ID_C", length = 36)
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity ID.
|
||||||
|
*/
|
||||||
|
@Column(name = "LOG_IDENTITY_C", nullable = false, length = 36)
|
||||||
|
private String entityId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity class.
|
||||||
|
*/
|
||||||
|
@Column(name = "LOG_CLASSENTITY_C", nullable = false, length = 50)
|
||||||
|
private String entityClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log type.
|
||||||
|
*/
|
||||||
|
@Column(name = "LOG_TYPE_C", nullable = false, length = 50)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private AuditLogType type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log message.
|
||||||
|
*/
|
||||||
|
@Column(name = "LOG_MESSAGE_C", length = 1000)
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creation date.
|
||||||
|
*/
|
||||||
|
@Column(name = "LOG_CREATEDATE_D", nullable = false)
|
||||||
|
private Date createDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of id.
|
||||||
|
*
|
||||||
|
* @return id
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of id.
|
||||||
|
*
|
||||||
|
* @param id id
|
||||||
|
*/
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of entityId.
|
||||||
|
*
|
||||||
|
* @return entityId
|
||||||
|
*/
|
||||||
|
public String getEntityId() {
|
||||||
|
return entityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of entityId.
|
||||||
|
*
|
||||||
|
* @param entityId entityId
|
||||||
|
*/
|
||||||
|
public void setEntityId(String entityId) {
|
||||||
|
this.entityId = entityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of entityClass.
|
||||||
|
*
|
||||||
|
* @return entityClass
|
||||||
|
*/
|
||||||
|
public String getEntityClass() {
|
||||||
|
return entityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of entityClass.
|
||||||
|
*
|
||||||
|
* @param entityClass entityClass
|
||||||
|
*/
|
||||||
|
public void setEntityClass(String entityClass) {
|
||||||
|
this.entityClass = entityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of message.
|
||||||
|
*
|
||||||
|
* @return message
|
||||||
|
*/
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of message.
|
||||||
|
*
|
||||||
|
* @param message message
|
||||||
|
*/
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of type.
|
||||||
|
*
|
||||||
|
* @return type
|
||||||
|
*/
|
||||||
|
public AuditLogType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of type.
|
||||||
|
*
|
||||||
|
* @param type type
|
||||||
|
*/
|
||||||
|
public void setType(AuditLogType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of createDate.
|
||||||
|
*
|
||||||
|
* @return createDate
|
||||||
|
*/
|
||||||
|
public Date getCreateDate() {
|
||||||
|
return createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of createDate.
|
||||||
|
*
|
||||||
|
* @param createDate createDate
|
||||||
|
*/
|
||||||
|
public void setCreateDate(Date createDate) {
|
||||||
|
this.createDate = createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Objects.toStringHelper(this)
|
||||||
|
.add("id", id)
|
||||||
|
.add("entityId", entityId)
|
||||||
|
.add("entityClass", entityClass)
|
||||||
|
.add("type", type)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,14 @@
|
|||||||
package com.sismics.docs.core.model.jpa;
|
package com.sismics.docs.core.model.jpa;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EntityListeners;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,8 +17,9 @@ import java.util.Date;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@EntityListeners(AuditLogUtil.class)
|
||||||
@Table(name = "T_DOCUMENT")
|
@Table(name = "T_DOCUMENT")
|
||||||
public class Document {
|
public class Document implements Loggable {
|
||||||
/**
|
/**
|
||||||
* Document ID.
|
* Document ID.
|
||||||
*/
|
*/
|
||||||
@ -172,6 +176,7 @@ public class Document {
|
|||||||
*
|
*
|
||||||
* @return the deleteDate
|
* @return the deleteDate
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Date getDeleteDate() {
|
public Date getDeleteDate() {
|
||||||
return deleteDate;
|
return deleteDate;
|
||||||
}
|
}
|
||||||
@ -191,4 +196,9 @@ public class Document {
|
|||||||
.add("id", id)
|
.add("id", id)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toMessage() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package com.sismics.docs.core.model.jpa;
|
package com.sismics.docs.core.model.jpa;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EntityListeners;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Lob;
|
import javax.persistence.Lob;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,8 +18,9 @@ import java.util.Date;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@EntityListeners(AuditLogUtil.class)
|
||||||
@Table(name = "T_FILE")
|
@Table(name = "T_FILE")
|
||||||
public class File {
|
public class File implements Loggable {
|
||||||
/**
|
/**
|
||||||
* File ID.
|
* File ID.
|
||||||
*/
|
*/
|
||||||
@ -144,6 +148,7 @@ public class File {
|
|||||||
*
|
*
|
||||||
* @return the deleteDate
|
* @return the deleteDate
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Date getDeleteDate() {
|
public Date getDeleteDate() {
|
||||||
return deleteDate;
|
return deleteDate;
|
||||||
}
|
}
|
||||||
@ -217,4 +222,9 @@ public class File {
|
|||||||
.add("id", id)
|
.add("id", id)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toMessage() {
|
||||||
|
return documentId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.sismics.docs.core.model.jpa;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An entity which can be logged.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public interface Loggable {
|
||||||
|
/**
|
||||||
|
* Get a string representation of this entity for logging purpose.
|
||||||
|
* Avoid returning sensitive data like passwords.
|
||||||
|
*
|
||||||
|
* @return Entity message
|
||||||
|
*/
|
||||||
|
public String toMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loggable are soft deletable.
|
||||||
|
*
|
||||||
|
* @return deleteDate
|
||||||
|
*/
|
||||||
|
public Date getDeleteDate();
|
||||||
|
}
|
@ -1,11 +1,14 @@
|
|||||||
package com.sismics.docs.core.model.jpa;
|
package com.sismics.docs.core.model.jpa;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EntityListeners;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,8 +17,9 @@ import java.util.Date;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@EntityListeners(AuditLogUtil.class)
|
||||||
@Table(name = "T_TAG")
|
@Table(name = "T_TAG")
|
||||||
public class Tag {
|
public class Tag implements Loggable {
|
||||||
/**
|
/**
|
||||||
* Tag ID.
|
* Tag ID.
|
||||||
*/
|
*/
|
||||||
@ -148,6 +152,7 @@ public class Tag {
|
|||||||
*
|
*
|
||||||
* @return deleteDate
|
* @return deleteDate
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Date getDeleteDate() {
|
public Date getDeleteDate() {
|
||||||
return deleteDate;
|
return deleteDate;
|
||||||
}
|
}
|
||||||
@ -168,4 +173,9 @@ public class Tag {
|
|||||||
.add("name", name)
|
.add("name", name)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toMessage() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package com.sismics.docs.core.model.jpa;
|
package com.sismics.docs.core.model.jpa;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import java.util.Date;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EntityListeners;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import java.util.Date;
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User entity.
|
* User entity.
|
||||||
@ -14,8 +17,9 @@ import java.util.Date;
|
|||||||
* @author jtremeaux
|
* @author jtremeaux
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@EntityListeners(AuditLogUtil.class)
|
||||||
@Table(name = "T_USER")
|
@Table(name = "T_USER")
|
||||||
public class User {
|
public class User implements Loggable {
|
||||||
/**
|
/**
|
||||||
* User ID.
|
* User ID.
|
||||||
*/
|
*/
|
||||||
@ -250,6 +254,7 @@ public class User {
|
|||||||
*
|
*
|
||||||
* @return deleteDate
|
* @return deleteDate
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Date getDeleteDate() {
|
public Date getDeleteDate() {
|
||||||
return deleteDate;
|
return deleteDate;
|
||||||
}
|
}
|
||||||
@ -286,4 +291,9 @@ public class User {
|
|||||||
.add("username", username)
|
.add("username", username)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toMessage() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.sismics.docs.core.util;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
import com.sismics.docs.core.constant.AuditLogType;
|
||||||
|
import com.sismics.docs.core.dao.jpa.AuditLogDao;
|
||||||
|
import com.sismics.docs.core.model.jpa.AuditLog;
|
||||||
|
import com.sismics.docs.core.model.jpa.Loggable;
|
||||||
|
import com.sismics.util.context.ThreadLocalContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log utilities.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class AuditLogUtil {
|
||||||
|
/**
|
||||||
|
* Create an audit log.
|
||||||
|
*
|
||||||
|
* @param entity Entity
|
||||||
|
* @param type Audit log type
|
||||||
|
*/
|
||||||
|
public static void create(Loggable loggable, AuditLogType type) {
|
||||||
|
// Get the entity ID
|
||||||
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
|
String entityId = (String) em.getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(loggable);
|
||||||
|
|
||||||
|
// Create the audit log
|
||||||
|
AuditLogDao auditLogDao = new AuditLogDao();
|
||||||
|
AuditLog auditLog = new AuditLog();
|
||||||
|
auditLog.setEntityId(entityId);
|
||||||
|
auditLog.setEntityClass(loggable.getClass().getSimpleName());
|
||||||
|
auditLog.setType(type);
|
||||||
|
auditLog.setMessage(loggable.toMessage());
|
||||||
|
auditLogDao.create(auditLog);
|
||||||
|
}
|
||||||
|
}
|
@ -17,5 +17,6 @@
|
|||||||
<class>com.sismics.docs.core.model.jpa.DocumentTag</class>
|
<class>com.sismics.docs.core.model.jpa.DocumentTag</class>
|
||||||
<class>com.sismics.docs.core.model.jpa.Share</class>
|
<class>com.sismics.docs.core.model.jpa.Share</class>
|
||||||
<class>com.sismics.docs.core.model.jpa.Acl</class>
|
<class>com.sismics.docs.core.model.jpa.Acl</class>
|
||||||
|
<class>com.sismics.docs.core.model.jpa.AuditLog</class>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
</persistence>
|
</persistence>
|
@ -1,4 +1,6 @@
|
|||||||
alter table T_FILE alter column FIL_IDUSER_C set not null;
|
alter table T_FILE alter column FIL_IDUSER_C set not null;
|
||||||
alter table T_AUTHENTICATION_TOKEN add column AUT_IP_C varchar(45);
|
alter table T_AUTHENTICATION_TOKEN add column AUT_IP_C varchar(45);
|
||||||
alter table T_AUTHENTICATION_TOKEN add column AUT_UA_C varchar(1000);
|
alter table T_AUTHENTICATION_TOKEN add column AUT_UA_C varchar(1000);
|
||||||
|
create cached table T_AUDIT_LOG ( LOG_ID_C varchar(36) not null, LOG_IDENTITY_C varchar(36) not null, LOG_CLASSENTITY_C varchar(50) not null, LOG_TYPE_C varchar(50) not null, LOG_MESSAGE_C varchar(1000), LOG_CREATEDATE_D datetime, primary key (LOG_ID_C) );
|
||||||
|
create index IDX_LOG_COMPOSITE on T_AUDIT_LOG (LOG_IDENTITY_C, LOG_CLASSENTITY_C);
|
||||||
update T_CONFIG set CFG_VALUE_C='10' where CFG_ID_C='DB_VERSION';
|
update T_CONFIG set CFG_VALUE_C='10' where CFG_ID_C='DB_VERSION';
|
@ -117,8 +117,6 @@ public class RequestContextFilter implements Filter {
|
|||||||
throw new ServletException(e);
|
throw new ServletException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadLocalContext.cleanup();
|
|
||||||
|
|
||||||
// No error processing the request : commit / rollback the current transaction depending on the HTTP code
|
// No error processing the request : commit / rollback the current transaction depending on the HTTP code
|
||||||
if (em.isOpen()) {
|
if (em.isOpen()) {
|
||||||
@ -143,5 +141,7 @@ public class RequestContextFilter implements Filter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ThreadLocalContext.cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,17 +20,13 @@ import org.apache.log4j.Logger;
|
|||||||
import org.codehaus.jettison.json.JSONException;
|
import org.codehaus.jettison.json.JSONException;
|
||||||
import org.codehaus.jettison.json.JSONObject;
|
import org.codehaus.jettison.json.JSONObject;
|
||||||
|
|
||||||
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.criteria.DocumentCriteria;
|
|
||||||
import com.sismics.docs.core.dao.jpa.dto.DocumentDto;
|
|
||||||
import com.sismics.docs.core.model.context.AppContext;
|
import com.sismics.docs.core.model.context.AppContext;
|
||||||
import com.sismics.docs.core.model.jpa.File;
|
import com.sismics.docs.core.model.jpa.File;
|
||||||
import com.sismics.docs.core.util.ConfigUtil;
|
import com.sismics.docs.core.util.ConfigUtil;
|
||||||
import com.sismics.docs.core.util.DirectoryUtil;
|
import com.sismics.docs.core.util.DirectoryUtil;
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedList;
|
import com.sismics.docs.core.util.jpa.PaginatedList;
|
||||||
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
||||||
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.ForbiddenClientException;
|
import com.sismics.rest.exception.ForbiddenClientException;
|
||||||
import com.sismics.rest.exception.ServerException;
|
import com.sismics.rest.exception.ServerException;
|
||||||
@ -64,20 +60,6 @@ public class AppResource extends BaseResource {
|
|||||||
|
|
||||||
JSONObject response = new JSONObject();
|
JSONObject response = new JSONObject();
|
||||||
|
|
||||||
// Specific data
|
|
||||||
DocumentDao documentDao = new DocumentDao();
|
|
||||||
PaginatedList<DocumentDto> paginatedList = PaginatedLists.create(1, 0);
|
|
||||||
SortCriteria sortCriteria = new SortCriteria(0, true);
|
|
||||||
DocumentCriteria documentCriteria = new DocumentCriteria();
|
|
||||||
documentCriteria.setUserId(principal.getId());
|
|
||||||
try {
|
|
||||||
documentDao.findByCriteria(paginatedList, documentCriteria, sortCriteria);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new ServerException("SearchError", "Error searching in documents", e);
|
|
||||||
}
|
|
||||||
response.put("document_count", paginatedList.getResultCount());
|
|
||||||
|
|
||||||
// General data
|
|
||||||
response.put("current_version", currentVersion.replace("-SNAPSHOT", ""));
|
response.put("current_version", currentVersion.replace("-SNAPSHOT", ""));
|
||||||
response.put("min_version", minVersion);
|
response.put("min_version", minVersion);
|
||||||
response.put("total_memory", Runtime.getRuntime().totalMemory());
|
response.put("total_memory", Runtime.getRuntime().totalMemory());
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
package com.sismics.docs.rest.resource;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.codehaus.jettison.json.JSONException;
|
||||||
|
import org.codehaus.jettison.json.JSONObject;
|
||||||
|
|
||||||
|
import com.sismics.docs.core.constant.PermType;
|
||||||
|
import com.sismics.docs.core.dao.jpa.AclDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.AuditLogDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.criteria.AuditLogCriteria;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.AuditLogDto;
|
||||||
|
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.rest.exception.ForbiddenClientException;
|
||||||
|
import com.sismics.rest.exception.ServerException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log REST resources.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
@Path("/auditlog")
|
||||||
|
public class AuditLogResource extends BaseResource {
|
||||||
|
/**
|
||||||
|
* Returns the list of all logs for a document or user.
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
* @throws JSONException
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Response list(@QueryParam("document") String documentId) throws JSONException {
|
||||||
|
if (!authenticate()) {
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// On a document or a user?
|
||||||
|
PaginatedList<AuditLogDto> paginatedList = PaginatedLists.create(100, 0);
|
||||||
|
SortCriteria sortCriteria = new SortCriteria(1, true);
|
||||||
|
AuditLogCriteria criteria = new AuditLogCriteria();
|
||||||
|
if (documentId == null) {
|
||||||
|
// Search logs for a user
|
||||||
|
criteria.setUserId(principal.getId());
|
||||||
|
} else {
|
||||||
|
// Check ACL on the document
|
||||||
|
AclDao aclDao = new AclDao();
|
||||||
|
if (!aclDao.checkPermission(documentId, PermType.READ, principal.getId())) {
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
criteria.setDocumentId(documentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search the logs
|
||||||
|
try {
|
||||||
|
AuditLogDao auditLogDao = new AuditLogDao();
|
||||||
|
auditLogDao.findByCriteria(paginatedList, criteria, sortCriteria);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ServerException("SearchError", "Error searching in logs", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble the results
|
||||||
|
List<JSONObject> logs = new ArrayList<>();
|
||||||
|
JSONObject response = new JSONObject();
|
||||||
|
for (AuditLogDto auditLogDto : paginatedList.getResultList()) {
|
||||||
|
JSONObject log = new JSONObject();
|
||||||
|
log.put("id", auditLogDto.getId());
|
||||||
|
log.put("target", auditLogDto.getEntityId());
|
||||||
|
log.put("class", auditLogDto.getEntityClass());
|
||||||
|
log.put("type", auditLogDto.getType().name());
|
||||||
|
log.put("message", auditLogDto.getMessage());
|
||||||
|
log.put("create_date", auditLogDto.getCreateTimestamp());
|
||||||
|
logs.add(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the response
|
||||||
|
response.put("logs", logs);
|
||||||
|
response.put("total", paginatedList.getResultCount());
|
||||||
|
return Response.ok().entity(response).build();
|
||||||
|
}
|
||||||
|
}
|
@ -447,6 +447,8 @@ public class DocumentResource extends BaseResource {
|
|||||||
document.setLanguage(language);
|
document.setLanguage(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document = documentDao.update(document);
|
||||||
|
|
||||||
// Update tags
|
// Update tags
|
||||||
updateTagList(id, tagList);
|
updateTagList(id, tagList);
|
||||||
|
|
||||||
|
@ -175,6 +175,8 @@ public class TagResource extends BaseResource {
|
|||||||
tag.setColor(color);
|
tag.setColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tagDao.update(tag);
|
||||||
|
|
||||||
JSONObject response = new JSONObject();
|
JSONObject response = new JSONObject();
|
||||||
response.put("id", id);
|
response.put("id", id);
|
||||||
return Response.ok().entity(response).build();
|
return Response.ok().entity(response).build();
|
||||||
|
@ -9,6 +9,11 @@ angular.module('docs').controller('DocumentDefault', function($scope, $state, Re
|
|||||||
$scope.app = data;
|
$scope.app = data;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Load user audit log
|
||||||
|
Restangular.one('auditlog').get().then(function(data) {
|
||||||
|
$scope.logs = data.logs;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load unlinked files.
|
* Load unlinked files.
|
||||||
*/
|
*/
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
<img src="img/loader.gif" ng-show="!app" />
|
<img src="img/loader.gif" ng-show="!app" />
|
||||||
|
|
||||||
<div ng-show="app">
|
<div ng-show="app">
|
||||||
<h1>
|
|
||||||
{{ app.document_count }} <small>document{{ app.document_count > 1 ? 's' : '' }} in the database</small>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<div class="row upload-zone" ng-model="dropFiles" ng-file-drop drag-over-class="bg-success"
|
<div class="row upload-zone" ng-model="dropFiles" ng-file-drop drag-over-class="bg-success"
|
||||||
ng-multiple="true" allow-dir="false" accept="image/*,application/pdf,application/zip" ng-file-change="fileDropped($files, $event, $rejectedFiles)">
|
ng-multiple="true" allow-dir="false" accept="image/*,application/pdf,application/zip" ng-file-change="fileDropped($files, $event, $rejectedFiles)">
|
||||||
<div class="col-xs-6 col-sm-4 col-md-3 col-lg-2 text-center" ng-repeat="file in files">
|
<div class="col-xs-6 col-sm-4 col-md-3 col-lg-2 text-center" ng-repeat="file in files">
|
||||||
@ -45,6 +41,17 @@
|
|||||||
|
|
||||||
<div ui-view="file"></div>
|
<div ui-view="file"></div>
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Message</th>
|
||||||
|
</tr>
|
||||||
|
<tr ng-repeat="log in logs">
|
||||||
|
<td>{{ log.create_date | date: 'yyyy-MM-dd HH:mm' }}</td>
|
||||||
|
<td>{{ log.class }} {{ log.type }} {{ log.message }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
<div class="text-muted text-right">
|
<div class="text-muted text-right">
|
||||||
<ul class="list-inline">
|
<ul class="list-inline">
|
||||||
<li><strong>Version:</strong> {{ app.current_version }}</li>
|
<li><strong>Version:</strong> {{ app.current_version }}</li>
|
||||||
|
@ -41,7 +41,6 @@ public class TestAppResource extends BaseJerseyTest {
|
|||||||
Assert.assertTrue(freeMemory > 0);
|
Assert.assertTrue(freeMemory > 0);
|
||||||
Long totalMemory = json.getLong("total_memory");
|
Long totalMemory = json.getLong("total_memory");
|
||||||
Assert.assertTrue(totalMemory > 0 && totalMemory > freeMemory);
|
Assert.assertTrue(totalMemory > 0 && totalMemory > freeMemory);
|
||||||
Assert.assertEquals(0, json.getInt("document_count"));
|
|
||||||
|
|
||||||
// Rebuild Lucene index
|
// Rebuild Lucene index
|
||||||
appResource = resource().path("/app/batch/reindex");
|
appResource = resource().path("/app/batch/reindex");
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
package com.sismics.docs.rest;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.sismics.docs.rest.filter.CookieAuthenticationFilter;
|
||||||
|
import com.sun.jersey.api.client.ClientResponse;
|
||||||
|
import com.sun.jersey.api.client.ClientResponse.Status;
|
||||||
|
import com.sun.jersey.api.client.WebResource;
|
||||||
|
import com.sun.jersey.core.util.MultivaluedMapImpl;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.codehaus.jettison.json.JSONArray;
|
||||||
|
import org.codehaus.jettison.json.JSONException;
|
||||||
|
import org.codehaus.jettison.json.JSONObject;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the audit log resource.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class TestAuditLogResource extends BaseJerseyTest {
|
||||||
|
/**
|
||||||
|
* Test the audit log resource.
|
||||||
|
*
|
||||||
|
* @throws JSONException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testAuditLogResource() throws JSONException {
|
||||||
|
// Login auditlog1
|
||||||
|
clientUtil.createUser("auditlog1");
|
||||||
|
String auditlog1Token = clientUtil.login("auditlog1");
|
||||||
|
|
||||||
|
// Create a tag
|
||||||
|
WebResource tagResource = resource().path("/tag");
|
||||||
|
tagResource.addFilter(new CookieAuthenticationFilter(auditlog1Token));
|
||||||
|
MultivaluedMapImpl postParams = new MultivaluedMapImpl();
|
||||||
|
postParams.add("name", "SuperTag");
|
||||||
|
postParams.add("color", "#ffff00");
|
||||||
|
ClientResponse response = tagResource.put(ClientResponse.class, postParams);
|
||||||
|
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||||
|
JSONObject json = response.getEntity(JSONObject.class);
|
||||||
|
String tag1Id = json.optString("id");
|
||||||
|
Assert.assertNotNull(tag1Id);
|
||||||
|
|
||||||
|
// Create a document
|
||||||
|
WebResource documentResource = resource().path("/document");
|
||||||
|
documentResource.addFilter(new CookieAuthenticationFilter(auditlog1Token));
|
||||||
|
postParams = new MultivaluedMapImpl();
|
||||||
|
postParams.add("title", "My super title document 1");
|
||||||
|
postParams.add("description", "My super description for document 1");
|
||||||
|
postParams.add("tags", tag1Id);
|
||||||
|
postParams.add("language", "eng");
|
||||||
|
long create1Date = new Date().getTime();
|
||||||
|
postParams.add("create_date", create1Date);
|
||||||
|
response = documentResource.put(ClientResponse.class, postParams);
|
||||||
|
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||||
|
json = response.getEntity(JSONObject.class);
|
||||||
|
String document1Id = json.optString("id");
|
||||||
|
Assert.assertNotNull(document1Id);
|
||||||
|
|
||||||
|
// Get all logs for the document
|
||||||
|
WebResource auditLogResource = resource().path("/auditlog");
|
||||||
|
auditLogResource.addFilter(new CookieAuthenticationFilter(auditlog1Token));
|
||||||
|
response = auditLogResource.queryParam("document", document1Id).get(ClientResponse.class);
|
||||||
|
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||||
|
json = response.getEntity(JSONObject.class);
|
||||||
|
JSONArray logs = json.getJSONArray("logs");
|
||||||
|
Assert.assertTrue(logs.length() == 3);
|
||||||
|
|
||||||
|
// Get all logs for the current user
|
||||||
|
auditLogResource = resource().path("/auditlog");
|
||||||
|
auditLogResource.addFilter(new CookieAuthenticationFilter(auditlog1Token));
|
||||||
|
response = auditLogResource.get(ClientResponse.class);
|
||||||
|
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||||
|
json = response.getEntity(JSONObject.class);
|
||||||
|
logs = json.getJSONArray("logs");
|
||||||
|
Assert.assertTrue(logs.length() == 3);
|
||||||
|
|
||||||
|
// Deletes a tag
|
||||||
|
tagResource = resource().path("/tag/" + tag1Id);
|
||||||
|
tagResource.addFilter(new CookieAuthenticationFilter(auditlog1Token));
|
||||||
|
response = tagResource.delete(ClientResponse.class);
|
||||||
|
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||||
|
json = response.getEntity(JSONObject.class);
|
||||||
|
Assert.assertEquals("ok", json.getString("status"));
|
||||||
|
|
||||||
|
// Get all logs for the current user
|
||||||
|
auditLogResource = resource().path("/auditlog");
|
||||||
|
auditLogResource.addFilter(new CookieAuthenticationFilter(auditlog1Token));
|
||||||
|
response = auditLogResource.get(ClientResponse.class);
|
||||||
|
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||||
|
json = response.getEntity(JSONObject.class);
|
||||||
|
logs = json.getJSONArray("logs");
|
||||||
|
Assert.assertTrue(logs.length() == 4);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user