Adding annotation entity touch event

This commit is contained in:
Thomas Georgios Giannos 2024-03-11 15:55:52 +02:00
parent 06e6ee406b
commit 7347fbbd5a
27 changed files with 704 additions and 143 deletions

View File

@ -42,9 +42,10 @@ queue:
options:
exchange: null
tenant-removal-topic: tenant.remove
tenant-touched-topic: tenant.touch
tenant-touch-topic: tenant.touch
user-removal-topic: user.remove
user-touched-topic: user.touch
user-touch-topic: user.touch
annotation-entity-touch-topic: annotation.entity.touch
rabbitmq:
enable: false
interval-seconds: 30

View File

@ -51,4 +51,9 @@ public class AuditableAction {
public static final EventId Annotation_Persist = new EventId(24002, "Annotation_Persist");
public static final EventId Annotation_Delete = new EventId(24003, "Annotation_Delete");
public static final EventId Entity_User_Query = new EventId(25000, "Entity_User_Query");
public static final EventId Entity_User_Lookup = new EventId(25001, "Entity_User_Lookup");
public static final EventId Entity_User_Persist = new EventId(25002, "Entity_User_Persist");
public static final EventId Entity_User_Delete = new EventId(25003, "Entity_User_Delete");
}

View File

@ -0,0 +1,35 @@
package gr.cite.annotation.common.validation;
import gr.cite.annotation.convention.ConventionService;
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
import gr.cite.tools.validation.specification.Specification;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class UuidValidator extends BaseValidator<UUID> {
private final MessageSource messageSource;
protected UuidValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
super(conventionService, errors);
this.messageSource = messageSource;
}
@Override
protected Class<UUID> modelClass() {
return UUID.class;
}
@Override
protected List<Specification> specifications(UUID item) {
return Arrays.asList(
this.spec()
.must(() -> this.isValidGuid(item))
.failOn("uuid").failWith(messageSource.getMessage("Validation_Required", new Object[]{"uuid"}, LocaleContextHolder.getLocale()))
);
}
}

View File

@ -33,9 +33,10 @@ public class AppRabbitConfigurer extends RabbitConfigurer {
public InboxBindings inboxBindingsCreator() {
List<String> bindingItems = new ArrayList<>();
bindingItems.addAll(this.inboxProperties.getTenantRemovalTopic());
bindingItems.addAll(this.inboxProperties.getTenantTouchedTopic());
bindingItems.addAll(this.inboxProperties.getTenantTouchTopic());
bindingItems.addAll(this.inboxProperties.getUserRemovalTopic());
bindingItems.addAll(this.inboxProperties.getUserTouchedTopic());
bindingItems.addAll(this.inboxProperties.getUserTouchTopic());
bindingItems.addAll(this.inboxProperties.getAnnotationEntityTouchTopic());
return new InboxBindings(bindingItems);
}

View File

@ -11,39 +11,47 @@ public class InboxProperties {
private final List<String> tenantRemovalTopic;
private final List<String> tenantTouchedTopic;
private final List<String> tenantTouchTopic;
private final List<String> userRemovalTopic;
private final List<String> userTouchedTopic;
private final List<String> userTouchTopic;
private final List<String> annotationEntityTouchTopic;
public InboxProperties(
String exchange,
List<String> tenantRemovalTopic,
List<String> tenantTouchedTopic,
List<String> tenantTouchTopic,
List<String> userRemovalTopic,
List<String> userTouchedTopic) {
List<String> userTouchTopic,
List<String> annotationEntityTouchTopic) {
this.exchange = exchange;
this.tenantRemovalTopic = tenantRemovalTopic;
this.tenantTouchedTopic = tenantTouchedTopic;
this.tenantTouchTopic = tenantTouchTopic;
this.userRemovalTopic = userRemovalTopic;
this.userTouchedTopic = userTouchedTopic;
this.userTouchTopic = userTouchTopic;
this.annotationEntityTouchTopic = annotationEntityTouchTopic;
}
public List<String> getTenantRemovalTopic() {
return tenantRemovalTopic;
}
public List<String> getTenantTouchedTopic() {
return tenantTouchedTopic;
public List<String> getTenantTouchTopic() {
return tenantTouchTopic;
}
public List<String> getUserRemovalTopic() {
return userRemovalTopic;
}
public List<String> getUserTouchedTopic() {
return userTouchedTopic;
public List<String> getUserTouchTopic() {
return userTouchTopic;
}
public List<String> getAnnotationEntityTouchTopic() {
return annotationEntityTouchTopic;
}
public String getExchange() {

View File

@ -5,10 +5,11 @@ import gr.cite.annotation.common.enums.IsActive;
import gr.cite.annotation.common.scope.fake.FakeRequestScope;
import gr.cite.annotation.data.QueueInboxEntity;
import gr.cite.annotation.integrationevent.TrackedEvent;
import gr.cite.annotation.integrationevent.inbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
import gr.cite.annotation.integrationevent.inbox.tenantremoval.TenantRemovalIntegrationEventHandler;
import gr.cite.annotation.integrationevent.inbox.tenanttouched.TenantTouchedIntegrationEventHandler;
import gr.cite.annotation.integrationevent.inbox.tenanttouch.TenantTouchedIntegrationEventHandler;
import gr.cite.annotation.integrationevent.inbox.userremoval.UserRemovalIntegrationEventHandler;
import gr.cite.annotation.integrationevent.inbox.usertouched.UserTouchedIntegrationEventHandler;
import gr.cite.annotation.integrationevent.inbox.usertouch.UserTouchedIntegrationEventHandler;
import gr.cite.annotation.query.QueueInboxQuery;
import gr.cite.queueinbox.entity.QueueInbox;
import gr.cite.queueinbox.entity.QueueInboxStatus;
@ -325,12 +326,14 @@ public class InboxRepositoryImpl implements InboxRepository {
logger.debug("Processing message with routing key '{}'", routingKey);
if (this.routingKeyMatched(routingKey, this.inboxProperties.getTenantRemovalTopic()))
handler = this.applicationContext.getBean(TenantRemovalIntegrationEventHandler.class);
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getTenantTouchedTopic()))
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getTenantTouchTopic()))
handler = this.applicationContext.getBean(TenantTouchedIntegrationEventHandler.class);
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getUserRemovalTopic()))
handler = this.applicationContext.getBean(UserRemovalIntegrationEventHandler.class);
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getUserTouchedTopic()))
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getUserTouchTopic()))
handler = this.applicationContext.getBean(UserTouchedIntegrationEventHandler.class);
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getAnnotationEntityTouchTopic()))
handler = this.applicationContext.getBean(AnnotationEntityTouchedIntegrationEventHandler.class);
else {
logger.error("No handler found for message routing key '{}'. Discarding.", routingKey);
handler = null;

View File

@ -0,0 +1,85 @@
package gr.cite.annotation.integrationevent.inbox.annotationentitytouch;
import gr.cite.annotation.common.validation.BaseValidator;
import gr.cite.annotation.common.validation.UuidValidator;
import gr.cite.annotation.convention.ConventionService;
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
import gr.cite.tools.validation.ValidatorFactory;
import gr.cite.tools.validation.specification.Specification;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class AnnotationEntityTouchedIntegrationEvent {
private UUID entityId;
public static final String _entityId = "entityId";
private List<UUID> userIds;
public static final String _userIds = "userIds";
public UUID getEntityId() {
return entityId;
}
public void setEntityId(UUID entityId) {
this.entityId = entityId;
}
public List<UUID> getUserIds() {
return userIds;
}
public void setUserIds(List<UUID> userIds) {
this.userIds = userIds;
}
@Component(AnnotationEntityTouchedIntegrationEvent.AnnotationEntityTouchedIntegrationEventValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class AnnotationEntityTouchedIntegrationEventValidator extends BaseValidator<AnnotationEntityTouchedIntegrationEvent> {
public static final String ValidatorName = "AnnotationEntityTouchedIntegrationEventValidator";
private final MessageSource messageSource;
private final ValidatorFactory validatorFactory;
protected AnnotationEntityTouchedIntegrationEventValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, ValidatorFactory validatorFactory) {
super(conventionService, errors);
this.messageSource = messageSource;
this.validatorFactory = validatorFactory;
}
@Override
protected Class<AnnotationEntityTouchedIntegrationEvent> modelClass() {
return AnnotationEntityTouchedIntegrationEvent.class;
}
@Override
protected List<Specification> specifications(AnnotationEntityTouchedIntegrationEvent item) {
return Arrays.asList(
this.spec()
.iff(() -> !this.isNull(item.getEntityId()))
.must(() -> this.isValidGuid(item.getEntityId()))
.failOn(AnnotationEntityTouchedIntegrationEvent._entityId).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityTouchedIntegrationEvent._entityId}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isListNullOrEmpty(item.getUserIds()))
.failOn(AnnotationEntityTouchedIntegrationEvent._userIds).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityTouchedIntegrationEvent._userIds}, LocaleContextHolder.getLocale())),
this.navSpec()
.iff(() -> !this.isListNullOrEmpty(item.getUserIds()))
.on(AnnotationEntityTouchedIntegrationEvent._userIds)
.over(item.getUserIds())
.using((i) -> this.validatorFactory.validator(UuidValidator.class))
);
}
}
}

View File

@ -0,0 +1,7 @@
package gr.cite.annotation.integrationevent.inbox.annotationentitytouch;
import gr.cite.annotation.integrationevent.inbox.IntegrationEventHandler;
public interface AnnotationEntityTouchedIntegrationEventHandler extends IntegrationEventHandler {
}

View File

@ -0,0 +1,149 @@
package gr.cite.annotation.integrationevent.inbox.annotationentitytouch;
import gr.cite.annotation.audit.AuditableAction;
import gr.cite.annotation.common.JsonHandlingService;
import gr.cite.annotation.common.enums.IsActive;
import gr.cite.annotation.common.scope.fake.FakeRequestScope;
import gr.cite.annotation.data.EntityUserEntity;
import gr.cite.annotation.integrationevent.inbox.EventProcessingStatus;
import gr.cite.annotation.integrationevent.inbox.InboxPrincipal;
import gr.cite.annotation.integrationevent.inbox.IntegrationEventProperties;
import gr.cite.annotation.query.EntityUserQuery;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.tools.auditing.AuditService;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.validation.ValidatorFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.OptimisticLockException;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.AbstractMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AnnotationEntityTouchedIntegrationEventHandlerImpl implements AnnotationEntityTouchedIntegrationEventHandler {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(AnnotationEntityTouchedIntegrationEventHandlerImpl.class));
private final JsonHandlingService jsonHandlingService;
private final ValidatorFactory validatorFactory;
private final ApplicationContext applicationContext;
private final QueryFactory queryFactory;
public AnnotationEntityTouchedIntegrationEventHandlerImpl(JsonHandlingService jsonHandlingService, ValidatorFactory validatorFactory, ApplicationContext applicationContext, QueryFactory queryFactory) {
this.jsonHandlingService = jsonHandlingService;
this.validatorFactory = validatorFactory;
this.applicationContext = applicationContext;
this.queryFactory = queryFactory;
}
@Override
public EventProcessingStatus handle(IntegrationEventProperties properties, String message) {
AnnotationEntityTouchedIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(AnnotationEntityTouchedIntegrationEvent.class, message);
if (event == null)
return EventProcessingStatus.Error;
logger.debug("Handling {}", AnnotationEntityTouchedIntegrationEvent.class.getSimpleName());
this.validatorFactory.validator(AnnotationEntityTouchedIntegrationEvent.AnnotationEntityTouchedIntegrationEventValidator.class).validateForce(event);
EntityManager entityManager = null;
EntityTransaction transaction = null;
try (FakeRequestScope ignored = new FakeRequestScope()) {
try {
// QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
// TenantScope scope = this.applicationContext.getBean(TenantScope.class);
// if (scope.isMultitenant() && event.getTenant() != null) {
// TenantEntity tenant = queryFactory.query(TenantQuery.class).ids(event.getTenant()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code));
// if (tenant == null) {
// logger.error("missing tenant from event message");
// return EventProcessingStatus.Error;
// }
// scope.setTenant(event.getTenant(), tenant.getCode());
// } else if (scope.isMultitenant()) {
// logger.error("missing tenant from event message");
// return EventProcessingStatus.Error;
// }
//
// ValidationService validator = this.applicationContext.getBean(ValidationService.class);
// validator.validateForce(model);
CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class);
currentPrincipalResolver.push(InboxPrincipal.build(properties));
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
try {
EntityUserQuery entityUserQuery = this.queryFactory.query(EntityUserQuery.class);
List<EntityUserEntity> associatedUsersEntities = entityUserQuery
.entityIds(event.getEntityId())
.isActive(IsActive.Active)
.collect();
List<UUID> associatedUsers = associatedUsersEntities.stream()
.map(EntityUserEntity::getUserId)
.toList();
for (UUID user : event.getUserIds()) {
if (!associatedUsers.contains(user)) {
EntityUserEntity entityUserEntity = new EntityUserEntity();
entityUserEntity.setId(UUID.randomUUID());
entityUserEntity.setEntityId(event.getEntityId());
entityUserEntity.setUserId(user);
entityUserEntity.setCreatedAt(Instant.now());
entityUserEntity.setUpdatedAt(Instant.now());
entityUserEntity.setIsActive(IsActive.Active);
entityManager.persist(entityUserEntity);
}
}
AuditService auditService = this.applicationContext.getBean(AuditService.class);
auditService.track(AuditableAction.User_Persist, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("model", event)
));
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
} finally {
currentPrincipalResolver.pop();
}
} catch (OptimisticLockException ex) {
// we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working
logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage());
if (transaction != null)
transaction.rollback();
} catch (Exception ex) {
logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
if (transaction != null)
transaction.rollback();
} finally {
if (entityManager != null)
entityManager.close();
}
} catch (Exception ex) {
logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
}
return EventProcessingStatus.Success;
}
}

View File

@ -1,4 +1,4 @@
package gr.cite.annotation.integrationevent.inbox.tenanttouched;
package gr.cite.annotation.integrationevent.inbox.tenanttouch;
import gr.cite.annotation.integrationevent.TrackedEvent;

View File

@ -1,4 +1,4 @@
package gr.cite.annotation.integrationevent.inbox.tenanttouched;
package gr.cite.annotation.integrationevent.inbox.tenanttouch;
import gr.cite.annotation.integrationevent.inbox.IntegrationEventHandler;

View File

@ -1,4 +1,4 @@
package gr.cite.annotation.integrationevent.inbox.tenanttouched;
package gr.cite.annotation.integrationevent.inbox.tenanttouch;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.annotation.audit.AuditableAction;

View File

@ -1,4 +1,4 @@
package gr.cite.annotation.integrationevent.inbox.usertouched;
package gr.cite.annotation.integrationevent.inbox.usertouch;
import gr.cite.annotation.common.enums.ContactInfoType;
import gr.cite.annotation.common.validation.BaseValidator;

View File

@ -1,4 +1,4 @@
package gr.cite.annotation.integrationevent.inbox.usertouched;
package gr.cite.annotation.integrationevent.inbox.usertouch;
import gr.cite.annotation.integrationevent.inbox.IntegrationEventHandler;

View File

@ -1,4 +1,4 @@
package gr.cite.annotation.integrationevent.inbox.usertouched;
package gr.cite.annotation.integrationevent.inbox.usertouch;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.annotation.audit.AuditableAction;

View File

@ -3,7 +3,7 @@ package gr.cite.annotation.model.persist;
import gr.cite.annotation.common.validation.BaseValidator;
import gr.cite.annotation.convention.ConventionService;
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
import gr.cite.annotation.integrationevent.inbox.usertouched.UserTouchedIntegrationEvent;
import gr.cite.annotation.integrationevent.inbox.usertouch.UserTouchedIntegrationEvent;
import gr.cite.tools.validation.specification.Specification;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource;

View File

@ -0,0 +1,146 @@
package gr.cite.annotation.query;
import gr.cite.annotation.authorization.AuthorizationFlags;
import gr.cite.annotation.common.enums.IsActive;
import gr.cite.annotation.data.EntityUserEntity;
import gr.cite.tools.data.query.FieldResolver;
import gr.cite.tools.data.query.QueryBase;
import gr.cite.tools.data.query.QueryContext;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Predicate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
import java.util.*;
@Component
@RequestScope
public class EntityUserQuery extends QueryBase<EntityUserEntity> {
private Collection<UUID> ids, entityIds, userIds;
private Collection<IsActive> isActives;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
public EntityUserQuery ids(UUID value) {
this.ids = List.of(value);
return this;
}
public EntityUserQuery ids(UUID... value) {
this.ids = Arrays.asList(value);
return this;
}
public EntityUserQuery ids(Collection<UUID> values) {
this.ids = values;
return this;
}
public EntityUserQuery entityIds(UUID value) {
this.entityIds = List.of(value);
return this;
}
public EntityUserQuery entityIds(UUID... value) {
this.entityIds = Arrays.asList(value);
return this;
}
public EntityUserQuery entityIds(Collection<UUID> values) {
this.entityIds = values;
return this;
}
public EntityUserQuery userIds(UUID value) {
this.userIds = List.of(value);
return this;
}
public EntityUserQuery userIds(UUID... value) {
this.userIds = Arrays.asList(value);
return this;
}
public EntityUserQuery userIds(Collection<UUID> values) {
this.userIds = values;
return this;
}
public EntityUserQuery isActive(IsActive value) {
this.isActives = List.of(value);
return this;
}
public EntityUserQuery isActive(IsActive... value) {
this.isActives = Arrays.asList(value);
return this;
}
public EntityUserQuery isActive(Collection<IsActive> values) {
this.isActives = values;
return this;
}
public EntityUserQuery authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
protected Boolean isFalseQuery() {
return false;
}
@Override
protected Class<EntityUserEntity> entityClass() {
return EntityUserEntity.class;
}
@Override
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
List<Predicate> predicates = new ArrayList<>();
if (this.ids != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(EntityUserEntity._id));
for (UUID item : this.ids)
inClause.value(item);
predicates.add(inClause);
}
if (this.entityIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(EntityUserEntity._entityId));
for (UUID item : this.entityIds)
inClause.value(item);
predicates.add(inClause);
}
if (this.userIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(EntityUserEntity._userId));
for (UUID item : this.userIds)
inClause.value(item);
predicates.add(inClause);
}
if (this.isActives != null) {
CriteriaBuilder.In<IsActive> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(EntityUserEntity._isActive));
for (IsActive item : this.isActives)
inClause.value(item);
predicates.add(inClause);
}
if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray);
} else {
return null;
}
}
@Override
protected String fieldNameOf(FieldResolver item) {
return null;
}
@Override
protected EntityUserEntity convert(Tuple tuple, Set<String> columns) {
return null;
}
}

View File

@ -1,6 +1,5 @@
package gr.cite.annotation.query;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.annotation.authorization.AuthorizationFlags;
import gr.cite.annotation.authorization.Permission;
import gr.cite.annotation.common.enums.IsActive;
@ -8,6 +7,7 @@ import gr.cite.annotation.common.scope.user.UserScope;
import gr.cite.annotation.data.UserEntity;
import gr.cite.annotation.model.User;
import gr.cite.annotation.model.user.PublicUser;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.query.FieldResolver;
import gr.cite.tools.data.query.QueryBase;
import gr.cite.tools.data.query.QueryContext;
@ -24,136 +24,151 @@ import java.util.*;
@RequestScope
public class UserQuery extends QueryBase<UserEntity> {
private String like;
private Collection<UUID> ids;
private Collection<IsActive> isActives;
private String like;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
private Collection<UUID> ids;
private final UserScope userScope;
private final AuthorizationService authService;
private Collection<IsActive> isActives;
public UserQuery(
UserScope userScope,
AuthorizationService authService
) {
this.userScope = userScope;
this.authService = authService;
}
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
public UserQuery like(String value) {
this.like = value;
return this;
}
private final UserScope userScope;
public UserQuery ids(UUID value) {
this.ids = List.of(value);
return this;
}
private final AuthorizationService authService;
public UserQuery ids(UUID... value) {
this.ids = Arrays.asList(value);
return this;
}
public UserQuery(
UserScope userScope,
AuthorizationService authService
) {
this.userScope = userScope;
this.authService = authService;
}
public UserQuery ids(Collection<UUID> values) {
this.ids = values;
return this;
}
public UserQuery like(String value) {
this.like = value;
return this;
}
public UserQuery isActive(IsActive value) {
this.isActives = List.of(value);
return this;
}
public UserQuery ids(UUID value) {
this.ids = List.of(value);
return this;
}
public UserQuery isActive(IsActive... value) {
this.isActives = Arrays.asList(value);
return this;
}
public UserQuery ids(UUID... value) {
this.ids = Arrays.asList(value);
return this;
}
public UserQuery isActive(Collection<IsActive> values) {
this.isActives = values;
return this;
}
public UserQuery ids(Collection<UUID> values) {
this.ids = values;
return this;
}
public UserQuery authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
public UserQuery isActive(IsActive value) {
this.isActives = List.of(value);
return this;
}
@Override
protected Class<UserEntity> entityClass() {
return UserEntity.class;
}
public UserQuery isActive(IsActive... value) {
this.isActives = Arrays.asList(value);
return this;
}
@Override
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) || this.isEmpty(this.isActives);
}
public UserQuery isActive(Collection<IsActive> values) {
this.isActives = values;
return this;
}
@Override
protected <X, Y> Predicate applyAuthZ(QueryContext<X, Y> queryContext) {
if (this.authorize.contains(AuthorizationFlags.None)) return null;
if (this.authorize.contains(AuthorizationFlags.Permission) && this.authService.authorize(Permission.BrowseUser)) return null;
UUID ownerId = null;
if (this.authorize.contains(AuthorizationFlags.Owner)) ownerId = this.userScope.getUserIdSafe();
public UserQuery authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
List<Predicate> predicates = new ArrayList<>();
if (ownerId != null) {
predicates.add(queryContext.CriteriaBuilder.equal(queryContext.Root.get(User._id), ownerId));
}
if (predicates.size() > 0) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray);
} else {
return queryContext.CriteriaBuilder.or(); //Creates a false query
}
}
@Override
protected Class<UserEntity> entityClass() {
return UserEntity.class;
}
@Override
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
List<Predicate> predicates = new ArrayList<>();
if (this.ids != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserEntity._id));
for (UUID item : this.ids) inClause.value(item);
predicates.add(inClause);
}
if (this.like != null && !this.like.isEmpty()) {
predicates.add(queryContext.CriteriaBuilder.like(queryContext.Root.get(UserEntity._name), this.like));
}
if (this.isActives != null) {
CriteriaBuilder.In<IsActive> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserEntity._isActive));
for (IsActive item : this.isActives) inClause.value(item);
predicates.add(inClause);
}
if (predicates.size() > 0) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray);
} else {
return null;
}
}
@Override
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) || this.isEmpty(this.isActives);
}
@Override
protected UserEntity convert(Tuple tuple, Set<String> columns) {
UserEntity item = new UserEntity();
item.setId(QueryBase.convertSafe(tuple, columns, UserEntity._id, UUID.class));
item.setName(QueryBase.convertSafe(tuple, columns, UserEntity._name, String.class));
item.setAdditionalInfo(QueryBase.convertSafe(tuple, columns, UserEntity._additionalInfo, String.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, UserEntity._createdAt, Instant.class));
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, UserEntity._updatedAt, Instant.class));
item.setIsActive(QueryBase.convertSafe(tuple, columns, UserEntity._isActive, IsActive.class));
return item;
}
@Override
protected <X, Y> Predicate applyAuthZ(QueryContext<X, Y> queryContext) {
if (this.authorize.contains(AuthorizationFlags.None))
return null;
if (this.authorize.contains(AuthorizationFlags.Permission) && this.authService.authorize(Permission.BrowseUser))
return null;
UUID ownerId = null;
if (this.authorize.contains(AuthorizationFlags.Owner))
ownerId = this.userScope.getUserIdSafe();
@Override
protected String fieldNameOf(FieldResolver item) {
if (item.match(User._id) || item.match(PublicUser._id)) return UserEntity._id;
else if (item.match(User._name) || item.match(PublicUser._name)) return UserEntity._name;
else if (item.match(User._createdAt) ) return UserEntity._createdAt;
else if (item.match(User._updatedAt)) return UserEntity._updatedAt;
else if (item.match(User._hash)) return UserEntity._updatedAt;
else if (item.match(User._isActive)) return UserEntity._isActive;
else return null;
}
List<Predicate> predicates = new ArrayList<>();
if (ownerId != null) {
predicates.add(queryContext.CriteriaBuilder.equal(queryContext.Root.get(User._id), ownerId));
}
if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray);
} else {
return queryContext.CriteriaBuilder.or(); //Creates a false query
}
}
@Override
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
List<Predicate> predicates = new ArrayList<>();
if (this.ids != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserEntity._id));
for (UUID item : this.ids)
inClause.value(item);
predicates.add(inClause);
}
if (this.like != null && !this.like.isEmpty()) {
predicates.add(queryContext.CriteriaBuilder.like(queryContext.Root.get(UserEntity._name), this.like));
}
if (this.isActives != null) {
CriteriaBuilder.In<IsActive> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserEntity._isActive));
for (IsActive item : this.isActives)
inClause.value(item);
predicates.add(inClause);
}
if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray);
} else {
return null;
}
}
@Override
protected UserEntity convert(Tuple tuple, Set<String> columns) {
UserEntity item = new UserEntity();
item.setId(QueryBase.convertSafe(tuple, columns, UserEntity._id, UUID.class));
item.setName(QueryBase.convertSafe(tuple, columns, UserEntity._name, String.class));
item.setAdditionalInfo(QueryBase.convertSafe(tuple, columns, UserEntity._additionalInfo, String.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, UserEntity._createdAt, Instant.class));
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, UserEntity._updatedAt, Instant.class));
item.setIsActive(QueryBase.convertSafe(tuple, columns, UserEntity._isActive, IsActive.class));
return item;
}
@Override
protected String fieldNameOf(FieldResolver item) {
if (item.match(User._id) || item.match(PublicUser._id))
return UserEntity._id;
else if (item.match(User._name) || item.match(PublicUser._name))
return UserEntity._name;
else if (item.match(User._createdAt))
return UserEntity._createdAt;
else if (item.match(User._updatedAt))
return UserEntity._updatedAt;
else if (item.match(User._hash))
return UserEntity._updatedAt;
else if (item.match(User._isActive))
return UserEntity._isActive;
else
return null;
}
}

View File

@ -1,7 +1,7 @@
package gr.cite.annotation.service.user;
import com.fasterxml.jackson.core.JsonProcessingException;
import gr.cite.annotation.integrationevent.inbox.usertouched.UserTouchedIntegrationEvent;
import gr.cite.annotation.integrationevent.inbox.usertouch.UserTouchedIntegrationEvent;
import gr.cite.annotation.model.User;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;

View File

@ -10,7 +10,7 @@ import gr.cite.annotation.convention.ConventionService;
import gr.cite.annotation.data.UserContactInfoEntity;
import gr.cite.annotation.data.UserCredentialEntity;
import gr.cite.annotation.data.UserEntity;
import gr.cite.annotation.integrationevent.inbox.usertouched.UserTouchedIntegrationEvent;
import gr.cite.annotation.integrationevent.inbox.usertouch.UserTouchedIntegrationEvent;
import gr.cite.annotation.model.User;
import gr.cite.annotation.model.builder.UserBuilder;
import gr.cite.annotation.model.deleter.UserDeleter;

View File

@ -27,6 +27,8 @@ public class OutboxIntegrationEvent extends IntegrationEvent {
public static final String DESCRIPTION_TOUCH = "DESCRIPTION_TOUCH";
public static final String ANNOTATION_ENTITY_TOUCH = "ANNOTATION_ENTITY_TOUCH";
public static final String WHAT_YOU_KNOW_ABOUT_ME_COMPLETED = "WHAT_YOU_KNOW_ABOUT_ME_COMPLETED";
public static final String GENERATE_FILE = "GENERATE_FILE";

View File

@ -23,6 +23,8 @@ public class OutboxProperties {
private final String descriptionTouchTopic;
private final String annotationEntityTouchTopic;
private final String notifyTopic;
private final String forgetMeCompletedTopic;
@ -37,7 +39,10 @@ public class OutboxProperties {
String tenantReactivationTopic,
String tenantUserInviteTopic,
String userRemovalTopic,
String userTouchTopic, String dmpTouchTopic, String descriptionTouchTopic,
String userTouchTopic,
String dmpTouchTopic,
String descriptionTouchTopic,
String annotationEntityTouchTopic,
String notifyTopic,
String forgetMeCompletedTopic,
String whatYouKnowAboutMeCompletedTopic,
@ -52,6 +57,7 @@ public class OutboxProperties {
this.userTouchTopic = userTouchTopic;
this.dmpTouchTopic = dmpTouchTopic;
this.descriptionTouchTopic = descriptionTouchTopic;
this.annotationEntityTouchTopic = annotationEntityTouchTopic;
this.notifyTopic = notifyTopic;
this.forgetMeCompletedTopic = forgetMeCompletedTopic;
this.whatYouKnowAboutMeCompletedTopic = whatYouKnowAboutMeCompletedTopic;
@ -94,6 +100,10 @@ public class OutboxProperties {
return descriptionTouchTopic;
}
public String getAnnotationEntityTouchTopic() {
return annotationEntityTouchTopic;
}
public String getNotifyTopic() {
return notifyTopic;
}

View File

@ -415,6 +415,10 @@ public class OutboxRepositoryImpl implements OutboxRepository {
routingKey = this.outboxProperties.getDescriptionTouchTopic();
break;
}
case OutboxIntegrationEvent.ANNOTATION_ENTITY_TOUCH: {
routingKey = this.outboxProperties.getAnnotationEntityTouchTopic();
break;
}
case OutboxIntegrationEvent.FORGET_ME_COMPLETED: {
routingKey = this.outboxProperties.getForgetMeCompletedTopic();
break;

View File

@ -0,0 +1,30 @@
package eu.eudat.integrationevent.outbox.annotationentitytouch;
import eu.eudat.integrationevent.TrackedEvent;
import java.util.List;
import java.util.UUID;
public class AnnotationEntityTouchedIntegrationEvent extends TrackedEvent {
private UUID entityId;
private List<UUID> userIds;
public UUID getEntityId() {
return entityId;
}
public void setEntityId(UUID entityId) {
this.entityId = entityId;
}
public List<UUID> getUserIds() {
return userIds;
}
public void setUserIds(List<UUID> userIds) {
this.userIds = userIds;
}
}

View File

@ -0,0 +1,25 @@
package eu.eudat.integrationevent.outbox.annotationentitytouch;
import eu.eudat.integrationevent.outbox.dmptouched.DmpTouchedIntegrationEvent;
import eu.eudat.model.persist.DmpPersist;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public interface AnnotationEntityTouchedIntegrationEventHandler {
void handle(AnnotationEntityTouchedIntegrationEvent event);
static AnnotationEntityTouchedIntegrationEvent buildEventFromPersistModel(DmpPersist persist) {
AnnotationEntityTouchedIntegrationEvent event = new AnnotationEntityTouchedIntegrationEvent();
event.setEntityId(persist.getId());
List<UUID> users = new ArrayList<>();
persist.getUsers().forEach(dmpUserPersist -> {
users.add(dmpUserPersist.getUser());
});
event.setUserIds(users);
return event;
}
}

View File

@ -0,0 +1,34 @@
package eu.eudat.integrationevent.outbox.annotationentitytouch;
import eu.eudat.integrationevent.outbox.OutboxIntegrationEvent;
import eu.eudat.integrationevent.outbox.OutboxService;
import gr.cite.tools.logging.LoggerService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AnnotationEntityTouchedIntegrationEventHandlerImpl implements AnnotationEntityTouchedIntegrationEventHandler {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(AnnotationEntityTouchedIntegrationEventHandlerImpl.class));
private final OutboxService outboxService;
public AnnotationEntityTouchedIntegrationEventHandlerImpl(OutboxService outboxService) {
this.outboxService = outboxService;
}
@Override
public void handle(AnnotationEntityTouchedIntegrationEvent event) {
OutboxIntegrationEvent message = new OutboxIntegrationEvent();
message.setMessageId(UUID.randomUUID());
message.setType(OutboxIntegrationEvent.ANNOTATION_ENTITY_TOUCH);
message.setEvent(event);
this.outboxService.publish(message);
}
}

View File

@ -35,6 +35,7 @@ queue:
user-removal-topic: user.remove
dmp-touch-topic: dmp.touch
description-touch-topic: description.touch
annotation-entity-touch-topic: annotation.entity.touch
what-you-know-about-me-completed-topic: whatyouknowaboutme.completed
generate-file-topic: generate.file
rabbitmq: