Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,30 @@
import com.fowoco.server.audit.application.port.AuditEventRepository;
import com.fowoco.server.audit.domain.AuditEvent;
import com.fowoco.server.audit.domain.AuditTargetType;
import jakarta.persistence.EntityManager;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Repository;

@Repository
public class JpaAuditEventRepository implements AuditEventRepository {

private final SpringDataAuditEventJpaRepository repository;
private final EntityManager entityManager;

public JpaAuditEventRepository(SpringDataAuditEventJpaRepository repository) {
public JpaAuditEventRepository(
SpringDataAuditEventJpaRepository repository,
EntityManager entityManager
) {
this.repository = repository;
this.entityManager = entityManager;
}

@Override
Expand Down Expand Up @@ -44,19 +55,57 @@ public List<AuditEvent> findTaskActivities(UUID companyId, UUID taskId) {

@Override
public List<AuditEvent> search(AuditSearchCriteria criteria) {
return repository.search(
criteria.companyId(),
criteria.actorType(),
criteria.action(),
criteria.targetType(),
criteria.targetId(),
criteria.traceId(),
criteria.createdFrom(),
criteria.createdTo(),
criteria.beforeCreatedAt(),
criteria.beforeAuditEventId(),
PageRequest.of(0, criteria.limit())
)
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<AuditEventJpaEntity> query = builder.createQuery(AuditEventJpaEntity.class);
Root<AuditEventJpaEntity> event = query.from(AuditEventJpaEntity.class);
List<Predicate> predicates = new ArrayList<>();

predicates.add(builder.equal(event.get("companyId"), criteria.companyId()));
if (criteria.actorType() != null) {
predicates.add(builder.equal(event.get("actorType"), criteria.actorType()));
}
if (criteria.action() != null) {
predicates.add(builder.equal(event.get("action"), criteria.action()));
}
if (criteria.targetType() != null) {
predicates.add(builder.equal(event.get("targetType"), criteria.targetType()));
}
if (criteria.targetId() != null) {
predicates.add(builder.equal(event.get("targetId"), criteria.targetId()));
}
if (criteria.traceId() != null) {
predicates.add(builder.equal(event.get("traceId"), criteria.traceId()));
}

var createdAt = event.<Instant>get("createdAt");
if (criteria.createdFrom() != null) {
predicates.add(builder.greaterThanOrEqualTo(createdAt, criteria.createdFrom()));
}
if (criteria.createdTo() != null) {
predicates.add(builder.lessThanOrEqualTo(createdAt, criteria.createdTo()));
}
if (criteria.beforeCreatedAt() != null) {
predicates.add(builder.or(
builder.lessThan(createdAt, criteria.beforeCreatedAt()),
builder.and(
builder.equal(createdAt, criteria.beforeCreatedAt()),
builder.lessThan(
event.<UUID>get("auditEventId"),
criteria.beforeAuditEventId()
)
)
));
}

query.where(predicates.toArray(Predicate[]::new));
query.orderBy(
builder.desc(createdAt),
builder.desc(event.get("auditEventId"))
);

return entityManager.createQuery(query)
.setMaxResults(criteria.limit())
.getResultList()
.stream()
.map(AuditEventJpaEntity::toDomain)
.toList();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
package com.fowoco.server.audit.infrastructure.persistence;

import com.fowoco.server.audit.domain.ActorType;
import com.fowoco.server.audit.domain.AuditAction;
import com.fowoco.server.audit.domain.AuditTargetType;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

interface SpringDataAuditEventJpaRepository extends JpaRepository<AuditEventJpaEntity, UUID> {

Expand All @@ -18,39 +12,4 @@ List<AuditEventJpaEntity> findTop200ByCompanyIdAndTargetTypeAndTargetIdOrderByCr
AuditTargetType targetType,
UUID targetId
);

@Query("""
SELECT event
FROM AuditEventJpaEntity event
WHERE event.companyId = :companyId
AND (:actorType IS NULL OR event.actorType = :actorType)
AND (:action IS NULL OR event.action = :action)
AND (:targetType IS NULL OR event.targetType = :targetType)
AND (:targetId IS NULL OR event.targetId = :targetId)
AND (:traceId IS NULL OR event.traceId = :traceId)
AND (:createdFrom IS NULL OR event.createdAt >= :createdFrom)
AND (:createdTo IS NULL OR event.createdAt <= :createdTo)
AND (
:beforeCreatedAt IS NULL
OR event.createdAt < :beforeCreatedAt
OR (
event.createdAt = :beforeCreatedAt
AND event.auditEventId < :beforeAuditEventId
)
)
ORDER BY event.createdAt DESC, event.auditEventId DESC
""")
List<AuditEventJpaEntity> search(
@Param("companyId") UUID companyId,
@Param("actorType") ActorType actorType,
@Param("action") AuditAction action,
@Param("targetType") AuditTargetType targetType,
@Param("targetId") UUID targetId,
@Param("traceId") String traceId,
@Param("createdFrom") Instant createdFrom,
@Param("createdTo") Instant createdTo,
@Param("beforeCreatedAt") Instant beforeCreatedAt,
@Param("beforeAuditEventId") UUID beforeAuditEventId,
Pageable pageable
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,30 @@

import com.fowoco.server.notification.application.port.NotificationRepository;
import com.fowoco.server.notification.domain.Notification;
import jakarta.persistence.EntityManager;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Repository;

@Repository
public class JpaNotificationRepository implements NotificationRepository {

private final SpringDataNotificationJpaRepository repository;
private final EntityManager entityManager;

public JpaNotificationRepository(SpringDataNotificationJpaRepository repository) {
public JpaNotificationRepository(
SpringDataNotificationJpaRepository repository,
EntityManager entityManager
) {
this.repository = repository;
this.entityManager = entityManager;
}

@Override
Expand All @@ -39,7 +49,27 @@ public Optional<Notification> findByIdAndCompanyId(UUID notificationId, UUID com

@Override
public List<Notification> findPage(UUID companyId, UUID userId, boolean unreadOnly, Instant cursor, int size) {
return repository.findPage(companyId, userId, unreadOnly, cursor, PageRequest.of(0, size)).stream()
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<NotificationJpaEntity> query = builder.createQuery(NotificationJpaEntity.class);
Root<NotificationJpaEntity> notification = query.from(NotificationJpaEntity.class);
List<Predicate> predicates = new ArrayList<>();

predicates.add(builder.equal(notification.get("companyId"), companyId));
predicates.add(builder.equal(notification.get("userId"), userId));
if (unreadOnly) {
predicates.add(builder.isFalse(notification.get("read")));
}
if (cursor != null) {
predicates.add(builder.lessThan(notification.<Instant>get("occurredAt"), cursor));
}

query.where(predicates.toArray(Predicate[]::new));
query.orderBy(builder.desc(notification.get("occurredAt")));

return entityManager.createQuery(query)
.setMaxResults(size)
.getResultList()
.stream()
.map(NotificationJpaEntity::toDomain)
.toList();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.fowoco.server.notification.infrastructure.persistence;

import java.time.Instant;
import java.util.UUID;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
Expand All @@ -20,22 +18,5 @@ java.util.Optional<NotificationJpaEntity> findByIdAndCompanyId(
@Param("companyId") UUID companyId
);

@Query("""
SELECT n
FROM NotificationJpaEntity n
WHERE n.companyId = :companyId
AND n.userId = :userId
AND (:unreadOnly = false OR n.read = false)
AND (:cursor IS NULL OR n.occurredAt < :cursor)
ORDER BY n.occurredAt DESC
""")
java.util.List<NotificationJpaEntity> findPage(
@Param("companyId") UUID companyId,
@Param("userId") UUID userId,
@Param("unreadOnly") boolean unreadOnly,
@Param("cursor") Instant cursor,
Pageable pageable
);

long countByCompanyIdAndUserIdAndReadFalse(UUID companyId, UUID userId);
}
Loading
Loading