Merge branch 'dmp-refactoring' of code-repo.d4science.org:MaDgiK-CITE/argos into dmp-refactoring
This commit is contained in:
commit
141ef488e5
|
@ -50,7 +50,7 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
EntityTransaction transaction = null;
|
EntityTransaction transaction = null;
|
||||||
EntityManager entityManager = null;
|
EntityManager entityManager = null;
|
||||||
CandidateInfo candidate = null;
|
CandidateInfo candidate = null;
|
||||||
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
try {
|
try {
|
||||||
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
|
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
|
||||||
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
@ -86,18 +86,18 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
} catch (OptimisticLockException ex) {
|
} catch (OptimisticLockException ex) {
|
||||||
// we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working
|
// we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working
|
||||||
this.logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage());
|
logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage());
|
||||||
if (transaction != null) transaction.rollback();
|
if (transaction != null) transaction.rollback();
|
||||||
candidate = null;
|
candidate = null;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
|
logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
|
||||||
if (transaction != null) transaction.rollback();
|
if (transaction != null) transaction.rollback();
|
||||||
candidate = null;
|
candidate = null;
|
||||||
} finally {
|
} finally {
|
||||||
if (entityManager != null) entityManager.close();
|
if (entityManager != null) entityManager.close();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
|
logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return candidate;
|
return candidate;
|
||||||
|
@ -107,9 +107,9 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
public Boolean shouldOmit(CandidateInfo candidate, Function<QueueOutbox, Boolean> shouldOmit) {
|
public Boolean shouldOmit(CandidateInfo candidate, Function<QueueOutbox, Boolean> shouldOmit) {
|
||||||
EntityTransaction transaction = null;
|
EntityTransaction transaction = null;
|
||||||
EntityManager entityManager = null;
|
EntityManager entityManager = null;
|
||||||
Boolean success = false;
|
boolean success = false;
|
||||||
|
|
||||||
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
try {
|
try {
|
||||||
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class).ids(candidate.getId()).first();
|
QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class).ids(candidate.getId()).first();
|
||||||
|
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
this.logger.warn("Could not lookup queue outbox {} to process. Continuing...", candidate.getId());
|
logger.warn("Could not lookup queue outbox {} to process. Continuing...", candidate.getId());
|
||||||
} else {
|
} else {
|
||||||
if (shouldOmit.apply(item)) {
|
if (shouldOmit.apply(item)) {
|
||||||
item.setNotifyStatus(QueueOutboxNotifyStatus.OMITTED);
|
item.setNotifyStatus(QueueOutboxNotifyStatus.OMITTED);
|
||||||
|
@ -135,14 +135,14 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
if (transaction != null) transaction.rollback();
|
if (transaction != null) transaction.rollback();
|
||||||
success = false;
|
success = false;
|
||||||
} finally {
|
} finally {
|
||||||
if (entityManager != null) entityManager.close();
|
if (entityManager != null) entityManager.close();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -151,9 +151,9 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
public Boolean shouldWait(CandidateInfo candidate, Function<QueueOutbox, Boolean> itIsTimeFunc) {
|
public Boolean shouldWait(CandidateInfo candidate, Function<QueueOutbox, Boolean> itIsTimeFunc) {
|
||||||
EntityTransaction transaction = null;
|
EntityTransaction transaction = null;
|
||||||
EntityManager entityManager = null;
|
EntityManager entityManager = null;
|
||||||
Boolean success = false;
|
boolean success = false;
|
||||||
|
|
||||||
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
try {
|
try {
|
||||||
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
|
||||||
|
@ -180,14 +180,14 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
}
|
}
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
if (transaction != null) transaction.rollback();
|
if (transaction != null) transaction.rollback();
|
||||||
success = false;
|
success = false;
|
||||||
} finally {
|
} finally {
|
||||||
if (entityManager != null) entityManager.close();
|
if (entityManager != null) entityManager.close();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
EntityManager entityManager = null;
|
EntityManager entityManager = null;
|
||||||
Boolean success = false;
|
Boolean success = false;
|
||||||
|
|
||||||
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
@ -211,7 +211,7 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class).ids(candidateInfo.getId()).first();
|
QueueOutboxEntity item = queryFactory.query(QueueOutboxQuery.class).ids(candidateInfo.getId()).first();
|
||||||
|
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
this.logger.warn("Could not lookup queue outbox {} to process. Continuing...", candidateInfo.getId());
|
logger.warn("Could not lookup queue outbox {} to process. Continuing...", candidateInfo.getId());
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
success = publish.apply(item);
|
success = publish.apply(item);
|
||||||
|
@ -235,14 +235,14 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
if (transaction != null) transaction.rollback();
|
if (transaction != null) transaction.rollback();
|
||||||
success = false;
|
success = false;
|
||||||
} finally {
|
} finally {
|
||||||
if (entityManager != null) entityManager.close();
|
if (entityManager != null) entityManager.close();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
EntityTransaction transaction = null;
|
EntityTransaction transaction = null;
|
||||||
EntityManager entityManager = null;
|
EntityManager entityManager = null;
|
||||||
|
|
||||||
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
@ -265,7 +265,7 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
List<QueueOutboxEntity> queueOutboxMessages = queryFactory.query(QueueOutboxQuery.class).ids(confirmedMessages).collect();
|
List<QueueOutboxEntity> queueOutboxMessages = queryFactory.query(QueueOutboxQuery.class).ids(confirmedMessages).collect();
|
||||||
|
|
||||||
if (queueOutboxMessages == null) {
|
if (queueOutboxMessages == null) {
|
||||||
this.logger.warn("Could not lookup messages {} to process. Continuing...", String.join(",", confirmedMessages.stream().map(x -> x.toString()).collect(Collectors.toList())));
|
logger.warn("Could not lookup messages {} to process. Continuing...", String.join(",", confirmedMessages.stream().map(x -> x.toString()).collect(Collectors.toList())));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
for (QueueOutboxEntity queueOutboxMessage : queueOutboxMessages) {
|
for (QueueOutboxEntity queueOutboxMessage : queueOutboxMessages) {
|
||||||
|
@ -279,13 +279,13 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
if (transaction != null) transaction.rollback();
|
if (transaction != null) transaction.rollback();
|
||||||
} finally {
|
} finally {
|
||||||
if (entityManager != null) entityManager.close();
|
if (entityManager != null) entityManager.close();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +294,7 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
EntityTransaction transaction = null;
|
EntityTransaction transaction = null;
|
||||||
EntityManager entityManager = null;
|
EntityManager entityManager = null;
|
||||||
|
|
||||||
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
@ -307,7 +307,7 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
List<QueueOutboxEntity> queueOutboxMessages = queryFactory.query(QueueOutboxQuery.class).ids(nackedMessages).collect();
|
List<QueueOutboxEntity> queueOutboxMessages = queryFactory.query(QueueOutboxQuery.class).ids(nackedMessages).collect();
|
||||||
|
|
||||||
if (queueOutboxMessages == null) {
|
if (queueOutboxMessages == null) {
|
||||||
this.logger.warn("Could not lookup messages {} to process. Continuing...", String.join(",", nackedMessages.stream().map(x -> x.toString()).collect(Collectors.toList())));
|
logger.warn("Could not lookup messages {} to process. Continuing...", String.join(",", nackedMessages.stream().map(x -> x.toString()).collect(Collectors.toList())));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
for (QueueOutboxEntity queueOutboxMessage : queueOutboxMessages) {
|
for (QueueOutboxEntity queueOutboxMessage : queueOutboxMessages) {
|
||||||
|
@ -321,13 +321,13 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
if (transaction != null) transaction.rollback();
|
if (transaction != null) transaction.rollback();
|
||||||
} finally {
|
} finally {
|
||||||
if (entityManager != null) entityManager.close();
|
if (entityManager != null) entityManager.close();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,9 +335,9 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
public QueueOutbox create(IntegrationEvent item) {
|
public QueueOutbox create(IntegrationEvent item) {
|
||||||
EntityTransaction transaction = null;
|
EntityTransaction transaction = null;
|
||||||
EntityManager entityManager = null;
|
EntityManager entityManager = null;
|
||||||
Boolean success = false;
|
boolean success = false;
|
||||||
QueueOutboxEntity queueMessage = null;
|
QueueOutboxEntity queueMessage = null;
|
||||||
try (FakeRequestScope fakeRequestScope = new FakeRequestScope()) {
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
try {
|
try {
|
||||||
queueMessage = this.mapEvent((OutboxIntegrationEvent) item);
|
queueMessage = this.mapEvent((OutboxIntegrationEvent) item);
|
||||||
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
@ -352,14 +352,14 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
if (transaction != null) transaction.rollback();
|
if (transaction != null) transaction.rollback();
|
||||||
success = false;
|
success = false;
|
||||||
} finally {
|
} finally {
|
||||||
if (entityManager != null) entityManager.close();
|
if (entityManager != null) entityManager.close();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
this.logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
}
|
}
|
||||||
return queueMessage;
|
return queueMessage;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,4 +15,4 @@ queue:
|
||||||
options:
|
options:
|
||||||
exchange: cite_dmp_devel_queue
|
exchange: cite_dmp_devel_queue
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
enable: false
|
enable: true
|
||||||
|
|
|
@ -26,11 +26,6 @@ queue:
|
||||||
options:
|
options:
|
||||||
exchange: null
|
exchange: null
|
||||||
forget-me-completed-topic: forgetme.completed
|
forget-me-completed-topic: forgetme.completed
|
||||||
notify-topic: notification.notify
|
|
||||||
tenant-reactivation-topic: tenant.reactivated
|
|
||||||
tenant-removal-topic: tenant.remove
|
|
||||||
tenant-touch-topic: tenant.touch
|
|
||||||
tenant-user-invite-topic: tenant.invite
|
|
||||||
what-you-know-about-me-completed-topic: whatyouknowaboutme.completed
|
what-you-know-about-me-completed-topic: whatyouknowaboutme.completed
|
||||||
generate-file-topic: generate.file
|
generate-file-topic: generate.file
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
|
@ -46,8 +41,11 @@ queue:
|
||||||
enable: false
|
enable: false
|
||||||
options:
|
options:
|
||||||
exchange: null
|
exchange: null
|
||||||
user-removal-topic: [ "user.remove" ]
|
notify-topic: notification.notify
|
||||||
user-touched-topic: [ "user.touch" ]
|
tenant-removal-topic: tenant.remove
|
||||||
|
tenant-touch-topic: tenant.touch
|
||||||
|
user-removal-topic: user.remove
|
||||||
|
user-touch-topic: user.touch
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
enable: false
|
enable: false
|
||||||
interval-seconds: 30
|
interval-seconds: 30
|
||||||
|
|
|
@ -15,4 +15,4 @@ queue:
|
||||||
options:
|
options:
|
||||||
exchange: cite_dmp_devel_queue
|
exchange: cite_dmp_devel_queue
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
enable: false
|
enable: true
|
||||||
|
|
|
@ -26,11 +26,6 @@ queue:
|
||||||
options:
|
options:
|
||||||
exchange: null
|
exchange: null
|
||||||
forget-me-completed-topic: forgetme.completed
|
forget-me-completed-topic: forgetme.completed
|
||||||
notify-topic: notification.notify
|
|
||||||
tenant-reactivation-topic: tenant.reactivated
|
|
||||||
tenant-removal-topic: tenant.remove
|
|
||||||
tenant-touch-topic: tenant.touch
|
|
||||||
tenant-user-invite-topic: tenant.invite
|
|
||||||
what-you-know-about-me-completed-topic: whatyouknowaboutme.completed
|
what-you-know-about-me-completed-topic: whatyouknowaboutme.completed
|
||||||
generate-file-topic: generate.file
|
generate-file-topic: generate.file
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
|
@ -46,8 +41,11 @@ queue:
|
||||||
enable: false
|
enable: false
|
||||||
options:
|
options:
|
||||||
exchange: null
|
exchange: null
|
||||||
user-removal-topic: [ "user.remove" ]
|
notify-topic: notification.notify
|
||||||
user-touched-topic: [ "user.touch" ]
|
tenant-removal-topic: tenant.remove
|
||||||
|
tenant-touch-topic: tenant.touch
|
||||||
|
user-removal-topic: user.remove
|
||||||
|
user-touch-topic: user.touch
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
enable: false
|
enable: false
|
||||||
interval-seconds: 30
|
interval-seconds: 30
|
||||||
|
|
|
@ -9,6 +9,16 @@ public class AuditableAction {
|
||||||
|
|
||||||
public static final EventId User_Available_Notifiers_Query = new EventId(10004, "User_Available_Notifiers_Query");
|
public static final EventId User_Available_Notifiers_Query = new EventId(10004, "User_Available_Notifiers_Query");
|
||||||
|
|
||||||
|
public static final EventId User_Query = new EventId(11000, "User_Query");
|
||||||
|
public static final EventId User_Lookup = new EventId(11001, "User_Lookup");
|
||||||
|
public static final EventId User_Persist = new EventId(11002, "User_Persist");
|
||||||
|
public static final EventId User_Delete = new EventId(11003, "User_Delete");
|
||||||
|
|
||||||
|
public static final EventId Tenant_Query = new EventId(12000, "Tenant_Query");
|
||||||
|
public static final EventId Tenant_Lookup = new EventId(12001, "Tenant_Lookup");
|
||||||
|
public static final EventId Tenant_Persist = new EventId(12002, "Tenant_Persist");
|
||||||
|
public static final EventId Tenant_Delete = new EventId(12003, "Tenant_Delete");
|
||||||
|
|
||||||
public static final EventId Notification_Query = new EventId(19000, "Notification_Query");
|
public static final EventId Notification_Query = new EventId(19000, "Notification_Query");
|
||||||
public static final EventId Notification_Lookup = new EventId(19001, "Notification_Lookup");
|
public static final EventId Notification_Lookup = new EventId(19001, "Notification_Lookup");
|
||||||
public static final EventId Notification_Persist = new EventId(19002, "Notification_Persist");
|
public static final EventId Notification_Persist = new EventId(19002, "Notification_Persist");
|
||||||
|
|
|
@ -3,14 +3,13 @@ package gr.cite.notification.common.enums;
|
||||||
import com.fasterxml.jackson.annotation.JsonValue;
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
import gr.cite.notification.data.conventers.DatabaseEnum;
|
import gr.cite.notification.data.conventers.DatabaseEnum;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public enum NotificationContactType implements DatabaseEnum<Short> {
|
public enum NotificationContactType implements DatabaseEnum<Short> {
|
||||||
EMAIL((short)0),
|
EMAIL((short) 0),
|
||||||
SLACK_BROADCAST((short)1),
|
SLACK_BROADCAST((short) 1),
|
||||||
SMS((short)2),
|
SMS((short) 2),
|
||||||
IN_APP((short)3);
|
IN_APP((short) 3);
|
||||||
|
|
||||||
private final Short value;
|
private final Short value;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package gr.cite.notification.integrationevent;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.inbox.InboxProperties;
|
||||||
|
import gr.cite.notification.integrationevent.outbox.OutboxProperties;
|
||||||
|
import gr.cite.queueinbox.repository.InboxRepository;
|
||||||
|
import gr.cite.rabbitmq.RabbitConfigurer;
|
||||||
|
import gr.cite.rabbitmq.consumer.InboxBindings;
|
||||||
|
import gr.cite.rabbitmq.consumer.InboxCreator;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties({OutboxProperties.class, InboxProperties.class})
|
||||||
|
@ConditionalOnProperty(prefix = "queue.rabbitmq", name = "listenerEnabled")
|
||||||
|
public class AppRabbitConfigurer extends RabbitConfigurer {
|
||||||
|
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private final InboxProperties inboxProperties;
|
||||||
|
|
||||||
|
public AppRabbitConfigurer(ApplicationContext applicationContext, InboxProperties inboxProperties) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
this.inboxProperties = inboxProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public InboxBindings inboxBindingsCreator() {
|
||||||
|
List<String> bindingItems = new ArrayList<>();
|
||||||
|
bindingItems.addAll(this.inboxProperties.getNotifyTopic());
|
||||||
|
bindingItems.addAll(this.inboxProperties.getTenantRemovalTopic());
|
||||||
|
bindingItems.addAll(this.inboxProperties.getTenantTouchedTopic());
|
||||||
|
bindingItems.addAll(this.inboxProperties.getUserRemovalTopic());
|
||||||
|
bindingItems.addAll(this.inboxProperties.getUserTouchedTopic());
|
||||||
|
|
||||||
|
return new InboxBindings(bindingItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public InboxCreator inboxCreator() {
|
||||||
|
return (params) -> {
|
||||||
|
InboxRepository inboxRepository = this.applicationContext.getBean(InboxRepository.class);
|
||||||
|
return inboxRepository.create(params) != null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package gr.cite.notification.integrationevent;
|
||||||
|
|
||||||
|
import gr.cite.rabbitmq.IntegrationEventContext;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class IntegrationEventContextImpl implements IntegrationEventContext {
|
||||||
|
|
||||||
|
private UUID tenant;
|
||||||
|
|
||||||
|
public IntegrationEventContextImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getTenant() {
|
||||||
|
return tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenant(UUID tenant) {
|
||||||
|
this.tenant = tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package gr.cite.notification.integrationevent;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class TrackedEvent {
|
||||||
|
|
||||||
|
public String trackingContextTag;
|
||||||
|
|
||||||
|
public String getTrackingContextTag() {
|
||||||
|
return trackingContextTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTrackingContextTag(String trackingContextTag) {
|
||||||
|
this.trackingContextTag = trackingContextTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox;
|
||||||
|
|
||||||
|
public interface ConsistencyHandler<T extends ConsistencyPredicates> {
|
||||||
|
|
||||||
|
Boolean isConsistent(T consistencyPredicates);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox;
|
||||||
|
|
||||||
|
public interface ConsistencyPredicates {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox;
|
||||||
|
|
||||||
|
public enum EventProcessingStatus {
|
||||||
|
Error,
|
||||||
|
Success,
|
||||||
|
Postponed,
|
||||||
|
Discard
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox;
|
||||||
|
|
||||||
|
import gr.cite.commons.web.oidc.principal.MyPrincipal;
|
||||||
|
import org.springframework.security.oauth2.core.ClaimAccessor;
|
||||||
|
import org.springframework.security.oauth2.jwt.JwtClaimNames;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class InboxPrincipal implements MyPrincipal, ClaimAccessor {
|
||||||
|
|
||||||
|
private final Map<String, Object> claims;
|
||||||
|
|
||||||
|
private final boolean isAuthenticated;
|
||||||
|
|
||||||
|
public InboxPrincipal(Boolean isAuthenticated, String name) {
|
||||||
|
this.claims = new HashMap<>();
|
||||||
|
this.put(JwtClaimNames.SUB, name);
|
||||||
|
this.isAuthenticated = isAuthenticated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InboxPrincipal build(IntegrationEventProperties properties) {
|
||||||
|
InboxPrincipal inboxPrincipal = new InboxPrincipal(true, "IntegrationEventQueueAppId");
|
||||||
|
inboxPrincipal.put("client_id", properties.getAppId());
|
||||||
|
inboxPrincipal.put("active", "true");
|
||||||
|
inboxPrincipal.put("nbf", Instant.now().minus(30, ChronoUnit.SECONDS).toString());
|
||||||
|
inboxPrincipal.put("exp", Instant.now().plus(10, ChronoUnit.MINUTES).toString());
|
||||||
|
return inboxPrincipal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean isAuthenticated() {
|
||||||
|
return this.isAuthenticated;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getClaims() {
|
||||||
|
return this.claims;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getClaimAsStringList(String claim) {
|
||||||
|
if (claims == null)
|
||||||
|
return null;
|
||||||
|
return this.getClaimAsStringList(claim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.getClaimAsString(JwtClaimNames.SUB);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String key, Object value) {
|
||||||
|
this.claims.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.ConstructorBinding;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Validated
|
||||||
|
@ConfigurationProperties(prefix = "queue.task.listener.options")
|
||||||
|
@ConstructorBinding
|
||||||
|
public class InboxProperties {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String exchange;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<String> notifyTopic;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<String> tenantRemovalTopic;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<String> tenantTouchedTopic;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<String> userRemovalTopic;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<String> userTouchedTopic;
|
||||||
|
|
||||||
|
public InboxProperties(
|
||||||
|
String exchange,
|
||||||
|
List<String> notifyTopic,
|
||||||
|
List<String> tenantRemovalTopic,
|
||||||
|
List<String> tenantTouchedTopic,
|
||||||
|
List<String> userRemovalTopic,
|
||||||
|
List<String> userTouchedTopic) {
|
||||||
|
this.exchange = exchange;
|
||||||
|
this.notifyTopic = notifyTopic;
|
||||||
|
this.tenantRemovalTopic = tenantRemovalTopic;
|
||||||
|
this.tenantTouchedTopic = tenantTouchedTopic;
|
||||||
|
this.userRemovalTopic = userRemovalTopic;
|
||||||
|
this.userTouchedTopic = userTouchedTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getNotifyTopic() {
|
||||||
|
return notifyTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getTenantRemovalTopic() {
|
||||||
|
return tenantRemovalTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getTenantTouchedTopic() {
|
||||||
|
return tenantTouchedTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getUserRemovalTopic() {
|
||||||
|
return userRemovalTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getUserTouchedTopic() {
|
||||||
|
return userTouchedTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExchange() {
|
||||||
|
return exchange;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,363 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox;
|
||||||
|
|
||||||
|
import gr.cite.notification.common.JsonHandlingService;
|
||||||
|
import gr.cite.notification.common.enums.IsActive;
|
||||||
|
import gr.cite.notification.common.scope.fake.FakeRequestScope;
|
||||||
|
import gr.cite.notification.data.QueueInboxEntity;
|
||||||
|
import gr.cite.notification.integrationevent.TrackedEvent;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.notify.NotifyIntegrationEventHandler;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.tenantremoval.TenantRemovalIntegrationEventHandler;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.tenanttouched.TenantTouchedIntegrationEventHandler;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.userremoval.UserRemovalIntegrationEventHandler;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.usertouched.UserTouchedIntegrationEventHandler;
|
||||||
|
import gr.cite.notification.query.QueueInboxQuery;
|
||||||
|
import gr.cite.queueinbox.entity.QueueInbox;
|
||||||
|
import gr.cite.queueinbox.entity.QueueInboxStatus;
|
||||||
|
import gr.cite.queueinbox.repository.CandidateInfo;
|
||||||
|
import gr.cite.queueinbox.repository.InboxRepository;
|
||||||
|
import gr.cite.queueinbox.task.MessageOptions;
|
||||||
|
import gr.cite.rabbitmq.consumer.InboxCreatorParams;
|
||||||
|
import gr.cite.tools.data.query.Ordering;
|
||||||
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
import jakarta.persistence.EntityManagerFactory;
|
||||||
|
import jakarta.persistence.EntityTransaction;
|
||||||
|
import jakarta.persistence.OptimisticLockException;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class InboxRepositoryImpl implements InboxRepository {
|
||||||
|
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(InboxRepositoryImpl.class));
|
||||||
|
|
||||||
|
protected final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private final JsonHandlingService jsonHandlingService;
|
||||||
|
|
||||||
|
private final InboxProperties inboxProperties;
|
||||||
|
|
||||||
|
public InboxRepositoryImpl(
|
||||||
|
ApplicationContext applicationContext,
|
||||||
|
InboxProperties inboxProperties
|
||||||
|
) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
this.jsonHandlingService = this.applicationContext.getBean(JsonHandlingService.class);
|
||||||
|
this.inboxProperties = inboxProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CandidateInfo candidate(Instant lastCandidateCreationTimestamp, MessageOptions options) {
|
||||||
|
EntityTransaction transaction = null;
|
||||||
|
EntityManager entityManager = null;
|
||||||
|
CandidateInfo candidate = null;
|
||||||
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
|
try {
|
||||||
|
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
|
||||||
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
entityManager = entityManagerFactory.createEntityManager();
|
||||||
|
|
||||||
|
transaction = entityManager.getTransaction();
|
||||||
|
transaction.begin();
|
||||||
|
|
||||||
|
QueueInboxEntity item = queryFactory.query(QueueInboxQuery.class)
|
||||||
|
.isActives(IsActive.Active)
|
||||||
|
.status(QueueInboxStatus.PENDING, QueueInboxStatus.ERROR)
|
||||||
|
.retryThreshold(options.getRetryThreashold())
|
||||||
|
.createdAfter(lastCandidateCreationTimestamp)
|
||||||
|
.ordering(new Ordering().addAscending(QueueInboxEntity._createdAt))
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (item != null) {
|
||||||
|
QueueInboxStatus prevState = item.getStatus();
|
||||||
|
item.setStatus(QueueInboxStatus.PROCESSING);
|
||||||
|
|
||||||
|
entityManager.merge(item);
|
||||||
|
entityManager.flush();
|
||||||
|
|
||||||
|
candidate = new CandidateInfo();
|
||||||
|
candidate.setId(item.getId());
|
||||||
|
candidate.setCreatedAt(item.getCreatedAt());
|
||||||
|
candidate.setPreviousState(prevState);
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} 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 inbox. Skipping: {} ", ex.getMessage());
|
||||||
|
if (transaction != null)
|
||||||
|
transaction.rollback();
|
||||||
|
candidate = null;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Problem getting list of queue inbox. Skipping: {}", ex.getMessage(), ex);
|
||||||
|
if (transaction != null)
|
||||||
|
transaction.rollback();
|
||||||
|
candidate = null;
|
||||||
|
} finally {
|
||||||
|
if (entityManager != null)
|
||||||
|
entityManager.close();
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Problem getting list of queue inbox. Skipping: {}", ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean shouldOmit(CandidateInfo candidate, Function<QueueInbox, Boolean> shouldOmit) {
|
||||||
|
EntityTransaction transaction = null;
|
||||||
|
EntityManager entityManager = null;
|
||||||
|
boolean success = false;
|
||||||
|
|
||||||
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
|
try {
|
||||||
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
|
||||||
|
entityManager = entityManagerFactory.createEntityManager();
|
||||||
|
transaction = entityManager.getTransaction();
|
||||||
|
|
||||||
|
transaction.begin();
|
||||||
|
|
||||||
|
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
|
||||||
|
QueueInboxEntity item = queryFactory.query(QueueInboxQuery.class).ids(candidate.getId()).first();
|
||||||
|
|
||||||
|
if (item == null) {
|
||||||
|
logger.warn("Could not lookup queue inbox {} to process. Continuing...", candidate.getId());
|
||||||
|
} else {
|
||||||
|
if (shouldOmit.apply(item)) {
|
||||||
|
item.setStatus(QueueInboxStatus.OMITTED);
|
||||||
|
|
||||||
|
entityManager.merge(item);
|
||||||
|
entityManager.flush();
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
|
if (transaction != null)
|
||||||
|
transaction.rollback();
|
||||||
|
success = false;
|
||||||
|
} finally {
|
||||||
|
if (entityManager != null)
|
||||||
|
entityManager.close();
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldWait(CandidateInfo candidate, Function<QueueInbox, Boolean> itIsTimeFunc) {
|
||||||
|
EntityTransaction transaction = null;
|
||||||
|
EntityManager entityManager = null;
|
||||||
|
boolean success = false;
|
||||||
|
|
||||||
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
|
try {
|
||||||
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
|
||||||
|
entityManager = entityManagerFactory.createEntityManager();
|
||||||
|
transaction = entityManager.getTransaction();
|
||||||
|
|
||||||
|
transaction.begin();
|
||||||
|
|
||||||
|
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
|
||||||
|
QueueInboxEntity item = queryFactory.query(QueueInboxQuery.class).ids(candidate.getId()).first();
|
||||||
|
|
||||||
|
if (item.getRetryCount() != null && item.getRetryCount() >= 1) {
|
||||||
|
Boolean itIsTime = itIsTimeFunc.apply(item);
|
||||||
|
|
||||||
|
if (!itIsTime) {
|
||||||
|
item.setStatus(candidate.getPreviousState());
|
||||||
|
|
||||||
|
entityManager.merge(item);
|
||||||
|
entityManager.flush();
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
success = !itIsTime;
|
||||||
|
}
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
|
if (transaction != null)
|
||||||
|
transaction.rollback();
|
||||||
|
success = false;
|
||||||
|
} finally {
|
||||||
|
if (entityManager != null)
|
||||||
|
entityManager.close();
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueueInbox create(InboxCreatorParams inboxCreatorParams) {
|
||||||
|
EntityTransaction transaction = null;
|
||||||
|
EntityManager entityManager = null;
|
||||||
|
boolean success = false;
|
||||||
|
QueueInboxEntity queueMessage = null;
|
||||||
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
|
try {
|
||||||
|
queueMessage = this.createQueueInboxEntity(inboxCreatorParams);
|
||||||
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
|
||||||
|
entityManager = entityManagerFactory.createEntityManager();
|
||||||
|
transaction = entityManager.getTransaction();
|
||||||
|
|
||||||
|
transaction.begin();
|
||||||
|
|
||||||
|
entityManager.persist(queueMessage);
|
||||||
|
entityManager.flush();
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
|
if (transaction != null)
|
||||||
|
transaction.rollback();
|
||||||
|
success = false;
|
||||||
|
} finally {
|
||||||
|
if (entityManager != null)
|
||||||
|
entityManager.close();
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
|
}
|
||||||
|
return queueMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private QueueInboxEntity createQueueInboxEntity(InboxCreatorParams inboxCreatorParams) {
|
||||||
|
|
||||||
|
QueueInboxEntity queueMessage = new QueueInboxEntity();
|
||||||
|
queueMessage.setId(UUID.randomUUID());
|
||||||
|
queueMessage.setTenantId(null);
|
||||||
|
queueMessage.setExchange(this.inboxProperties.getExchange());
|
||||||
|
queueMessage.setRoute(inboxCreatorParams.getRoutingKey());
|
||||||
|
queueMessage.setQueue(inboxCreatorParams.getQueueName());
|
||||||
|
queueMessage.setApplicationId(inboxCreatorParams.getAppId());
|
||||||
|
queueMessage.setMessageId(UUID.fromString(inboxCreatorParams.getMessageId()));
|
||||||
|
queueMessage.setMessage(inboxCreatorParams.getMessageBody());
|
||||||
|
queueMessage.setIsActive(IsActive.Active);
|
||||||
|
queueMessage.setStatus(QueueInboxStatus.PENDING);
|
||||||
|
queueMessage.setRetryCount(0);
|
||||||
|
queueMessage.setCreatedAt(Instant.now());
|
||||||
|
|
||||||
|
return queueMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean emit(CandidateInfo candidateInfo) {
|
||||||
|
EntityTransaction transaction = null;
|
||||||
|
EntityManager entityManager = null;
|
||||||
|
boolean success = false;
|
||||||
|
|
||||||
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
|
||||||
|
entityManager = entityManagerFactory.createEntityManager();
|
||||||
|
transaction = entityManager.getTransaction();
|
||||||
|
transaction.begin();
|
||||||
|
|
||||||
|
QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
|
||||||
|
QueueInboxEntity queueInboxMessage = queryFactory.query(QueueInboxQuery.class).ids(candidateInfo.getId()).first();
|
||||||
|
|
||||||
|
if (queueInboxMessage == null) {
|
||||||
|
logger.warn("Could not lookup queue inbox {} to process. Continuing...", candidateInfo.getId());
|
||||||
|
} else {
|
||||||
|
|
||||||
|
EventProcessingStatus status = this.processMessage(queueInboxMessage.getRoute(), queueInboxMessage.getMessageId().toString(), queueInboxMessage.getApplicationId(), queueInboxMessage.getMessage());
|
||||||
|
switch (status) {
|
||||||
|
case Success: {
|
||||||
|
queueInboxMessage.setStatus(QueueInboxStatus.SUCCESSFUL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Postponed: {
|
||||||
|
queueInboxMessage.setStatus(QueueInboxStatus.PARKED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Error: {
|
||||||
|
queueInboxMessage.setStatus(QueueInboxStatus.ERROR);
|
||||||
|
queueInboxMessage.setRetryCount(queueInboxMessage.getRetryCount() != null ? queueInboxMessage.getRetryCount() + 1 : 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Discard:
|
||||||
|
default: {
|
||||||
|
queueInboxMessage.setStatus(QueueInboxStatus.DISCARD);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
success = status == EventProcessingStatus.Success;
|
||||||
|
|
||||||
|
entityManager.merge(queueInboxMessage);
|
||||||
|
entityManager.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
|
if (transaction != null)
|
||||||
|
transaction.rollback();
|
||||||
|
success = false;
|
||||||
|
} finally {
|
||||||
|
if (entityManager != null)
|
||||||
|
entityManager.close();
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Problem executing purge. rolling back any db changes and marking error. Continuing...", ex);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EventProcessingStatus processMessage(String routingKey, String messageId, String appId, String message) {
|
||||||
|
IntegrationEventHandler handler;
|
||||||
|
if (this.routingKeyMatched(routingKey, this.inboxProperties.getNotifyTopic()))
|
||||||
|
handler = this.applicationContext.getBean(NotifyIntegrationEventHandler.class);
|
||||||
|
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getTenantRemovalTopic()))
|
||||||
|
handler = this.applicationContext.getBean(TenantRemovalIntegrationEventHandler.class);
|
||||||
|
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getTenantTouchedTopic()))
|
||||||
|
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()))
|
||||||
|
handler = this.applicationContext.getBean(UserTouchedIntegrationEventHandler.class);
|
||||||
|
else
|
||||||
|
handler = null;
|
||||||
|
|
||||||
|
if (handler == null)
|
||||||
|
return EventProcessingStatus.Discard;
|
||||||
|
|
||||||
|
IntegrationEventProperties properties = new IntegrationEventProperties();
|
||||||
|
properties.setAppId(appId);
|
||||||
|
properties.setMessageId(messageId);
|
||||||
|
|
||||||
|
TrackedEvent event = this.jsonHandlingService.fromJsonSafe(TrackedEvent.class, message);
|
||||||
|
// using (LogContext.PushProperty(this._logTrackingConfig.LogTrackingContextName, @event.TrackingContextTag))
|
||||||
|
// {
|
||||||
|
try {
|
||||||
|
return handler.handle(properties, message);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("problem handling event from routing key " + routingKey + ". Setting nack and continuing...", ex);
|
||||||
|
return EventProcessingStatus.Error;
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean routingKeyMatched(String routingKey, List<String> topics) {
|
||||||
|
if (topics == null || topics.isEmpty())
|
||||||
|
return false;
|
||||||
|
return topics.stream().anyMatch(x -> x.equals(routingKey));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox;
|
||||||
|
|
||||||
|
public interface IntegrationEventHandler {
|
||||||
|
|
||||||
|
EventProcessingStatus handle(IntegrationEventProperties properties, String message);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox;
|
||||||
|
|
||||||
|
public class IntegrationEventProperties {
|
||||||
|
|
||||||
|
private String messageId;
|
||||||
|
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
public String getMessageId() {
|
||||||
|
return messageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessageId(String messageId) {
|
||||||
|
this.messageId = messageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppId() {
|
||||||
|
return appId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppId(String appId) {
|
||||||
|
this.appId = appId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.notify;
|
||||||
|
|
||||||
|
import gr.cite.notification.common.StringUtils;
|
||||||
|
import gr.cite.notification.common.enums.IsActive;
|
||||||
|
import gr.cite.notification.common.enums.NotificationContactType;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.ConsistencyHandler;
|
||||||
|
import gr.cite.notification.model.User;
|
||||||
|
import gr.cite.notification.model.builder.UserBuilder;
|
||||||
|
import gr.cite.notification.query.UserQuery;
|
||||||
|
import gr.cite.tools.data.builder.BuilderFactory;
|
||||||
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
|
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class NotifyConsistencyHandler implements ConsistencyHandler<NotifyConsistencyPredicates> {
|
||||||
|
|
||||||
|
private final QueryFactory queryFactory;
|
||||||
|
|
||||||
|
private final BuilderFactory builderFactory;
|
||||||
|
|
||||||
|
public NotifyConsistencyHandler(QueryFactory queryFactory, BuilderFactory builderFactory) {
|
||||||
|
this.queryFactory = queryFactory;
|
||||||
|
this.builderFactory = builderFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean isConsistent(NotifyConsistencyPredicates consistencyPredicates) {
|
||||||
|
if (consistencyPredicates.getUserId() != null) {
|
||||||
|
UserQuery query = this.queryFactory.query(UserQuery.class).ids(consistencyPredicates.getUserId()).isActive(IsActive.Active);
|
||||||
|
|
||||||
|
BaseFieldSet fieldSet = new BaseFieldSet(
|
||||||
|
User._id,
|
||||||
|
User._isActive
|
||||||
|
);
|
||||||
|
User user = this.builderFactory.builder(UserBuilder.class).build(fieldSet, query.firstAs(fieldSet));
|
||||||
|
if (user == null)
|
||||||
|
return false;
|
||||||
|
return consistencyPredicates.getContactTypeHint() == null || consistencyPredicates.getContactTypeHint() == NotificationContactType.IN_APP || !StringUtils.isNullOrEmpty(consistencyPredicates.getContactHint());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.notify;
|
||||||
|
|
||||||
|
import gr.cite.notification.common.enums.NotificationContactType;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.ConsistencyPredicates;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class NotifyConsistencyPredicates implements ConsistencyPredicates {
|
||||||
|
|
||||||
|
private UUID userId;
|
||||||
|
|
||||||
|
private NotificationContactType contactTypeHint;
|
||||||
|
|
||||||
|
private String contactHint;
|
||||||
|
|
||||||
|
public NotifyConsistencyPredicates(UUID userId, NotificationContactType contactTypeHint, String contactHint) {
|
||||||
|
this.userId = userId;
|
||||||
|
this.contactTypeHint = contactTypeHint;
|
||||||
|
this.contactHint = contactHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(UUID userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotificationContactType getContactTypeHint() {
|
||||||
|
return contactTypeHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContactTypeHint(NotificationContactType contactTypeHint) {
|
||||||
|
this.contactTypeHint = contactTypeHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContactHint() {
|
||||||
|
return contactHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContactHint(String contactHint) {
|
||||||
|
this.contactHint = contactHint;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.notify;
|
||||||
|
|
||||||
|
import gr.cite.notification.common.enums.NotificationContactType;
|
||||||
|
import gr.cite.notification.integrationevent.TrackedEvent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class NotifyIntegrationEvent extends TrackedEvent {
|
||||||
|
|
||||||
|
private UUID userId;
|
||||||
|
|
||||||
|
private UUID tenantId;
|
||||||
|
|
||||||
|
private UUID notificationType;
|
||||||
|
|
||||||
|
private NotificationContactType contactTypeHint;
|
||||||
|
|
||||||
|
private String contactHint;
|
||||||
|
|
||||||
|
private String data;
|
||||||
|
|
||||||
|
private String provenanceRef;
|
||||||
|
|
||||||
|
public UUID getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(UUID userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getTenantId() {
|
||||||
|
return tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantId(UUID tenantId) {
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getNotificationType() {
|
||||||
|
return notificationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotificationType(UUID notificationType) {
|
||||||
|
this.notificationType = notificationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotificationContactType getContactTypeHint() {
|
||||||
|
return contactTypeHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContactTypeHint(NotificationContactType contactTypeHint) {
|
||||||
|
this.contactTypeHint = contactTypeHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContactHint() {
|
||||||
|
return contactHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContactHint(String contactHint) {
|
||||||
|
this.contactHint = contactHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProvenanceRef() {
|
||||||
|
return provenanceRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProvenanceRef(String provenanceRef) {
|
||||||
|
this.provenanceRef = provenanceRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.notify;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.inbox.IntegrationEventHandler;
|
||||||
|
|
||||||
|
public interface NotifyIntegrationEventHandler extends IntegrationEventHandler {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.notify;
|
||||||
|
|
||||||
|
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
||||||
|
import gr.cite.notification.audit.AuditableAction;
|
||||||
|
import gr.cite.notification.common.JsonHandlingService;
|
||||||
|
import gr.cite.notification.common.enums.NotificationNotifyState;
|
||||||
|
import gr.cite.notification.common.scope.fake.FakeRequestScope;
|
||||||
|
import gr.cite.notification.common.scope.tenant.TenantScope;
|
||||||
|
import gr.cite.notification.data.TenantEntity;
|
||||||
|
import gr.cite.notification.errorcode.ErrorThesaurusProperties;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.EventProcessingStatus;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.InboxPrincipal;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.IntegrationEventProperties;
|
||||||
|
import gr.cite.notification.model.Tenant;
|
||||||
|
import gr.cite.notification.model.persist.NotificationPersist;
|
||||||
|
import gr.cite.notification.query.TenantQuery;
|
||||||
|
import gr.cite.notification.service.notification.NotificationService;
|
||||||
|
import gr.cite.tools.auditing.AuditService;
|
||||||
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
|
import gr.cite.tools.exception.MyValidationException;
|
||||||
|
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
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.MessageSource;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class NotifyIntegrationEventHandlerImpl implements NotifyIntegrationEventHandler {
|
||||||
|
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(NotifyIntegrationEventHandlerImpl.class));
|
||||||
|
|
||||||
|
private final JsonHandlingService jsonHandlingService;
|
||||||
|
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private final ErrorThesaurusProperties errors;
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
public NotifyIntegrationEventHandlerImpl(JsonHandlingService jsonHandlingService, ApplicationContext applicationContext, ErrorThesaurusProperties errors, MessageSource messageSource) {
|
||||||
|
this.jsonHandlingService = jsonHandlingService;
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
this.errors = errors;
|
||||||
|
this.messageSource = messageSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventProcessingStatus handle(IntegrationEventProperties properties, String message) {
|
||||||
|
NotifyIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(NotifyIntegrationEvent.class, message);
|
||||||
|
if (event == null)
|
||||||
|
return EventProcessingStatus.Error;
|
||||||
|
if (event.getUserId() == null) {
|
||||||
|
throw new MyValidationException(this.errors.getModelValidation().getCode(), "userId", messageSource.getMessage("Validation_Required", new Object[]{"userId"}, LocaleContextHolder.getLocale()));
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationPersist model = new NotificationPersist();
|
||||||
|
model.setContactHint(event.getContactHint());
|
||||||
|
model.setContactTypeHint(event.getContactTypeHint());
|
||||||
|
model.setNotifiedWith(event.getContactTypeHint());
|
||||||
|
model.setData(event.getData());
|
||||||
|
model.setNotifyState(NotificationNotifyState.PENDING);
|
||||||
|
model.setType(event.getNotificationType());
|
||||||
|
|
||||||
|
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.getTenantId() != null) {
|
||||||
|
TenantEntity tenant = queryFactory.query(TenantQuery.class).ids(event.getTenantId()).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.getTenantId(), tenant.getCode());
|
||||||
|
} else if (scope.isMultitenant()) {
|
||||||
|
logger.error("missing tenant from event message");
|
||||||
|
return EventProcessingStatus.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class);
|
||||||
|
currentPrincipalResolver.push(InboxPrincipal.build(properties));
|
||||||
|
|
||||||
|
NotifyConsistencyHandler notifyConsistencyHandler = this.applicationContext.getBean(NotifyConsistencyHandler.class);
|
||||||
|
if (!(notifyConsistencyHandler.isConsistent(new NotifyConsistencyPredicates(event.getUserId(), event.getContactTypeHint(), event.getContactHint()))))
|
||||||
|
return EventProcessingStatus.Postponed;
|
||||||
|
|
||||||
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
entityManager = entityManagerFactory.createEntityManager();
|
||||||
|
|
||||||
|
transaction = entityManager.getTransaction();
|
||||||
|
transaction.begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
NotificationService notificationService = this.applicationContext.getBean(NotificationService.class);
|
||||||
|
notificationService.persist(model, new BaseFieldSet());
|
||||||
|
|
||||||
|
AuditService auditService = this.applicationContext.getBean(AuditService.class);
|
||||||
|
|
||||||
|
auditService.track(AuditableAction.Notification_Persist, Map.ofEntries(
|
||||||
|
new AbstractMap.SimpleEntry<String, Object>("id", event.getUserId())
|
||||||
|
));
|
||||||
|
//auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
transaction.rollback();
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
currentPrincipalResolver.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} 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 null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.tenantremoval;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.inbox.ConsistencyHandler;
|
||||||
|
import gr.cite.notification.query.TenantQuery;
|
||||||
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class TenantRemovalConsistencyHandler implements ConsistencyHandler<TenantRemovalConsistencyPredicates> {
|
||||||
|
|
||||||
|
private final QueryFactory queryFactory;
|
||||||
|
|
||||||
|
public TenantRemovalConsistencyHandler(QueryFactory queryFactory) {
|
||||||
|
this.queryFactory = queryFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean isConsistent(TenantRemovalConsistencyPredicates consistencyPredicates) {
|
||||||
|
long count = this.queryFactory.query(TenantQuery.class).ids(consistencyPredicates.getTenantId()).count();
|
||||||
|
return count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.tenantremoval;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.inbox.ConsistencyPredicates;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class TenantRemovalConsistencyPredicates implements ConsistencyPredicates {
|
||||||
|
|
||||||
|
private UUID tenantId;
|
||||||
|
|
||||||
|
public TenantRemovalConsistencyPredicates(UUID tenantId) {
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getTenantId() {
|
||||||
|
return tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantId(UUID tenantId) {
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.tenantremoval;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.TrackedEvent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class TenantRemovalIntegrationEvent extends TrackedEvent {
|
||||||
|
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.tenantremoval;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.inbox.IntegrationEventHandler;
|
||||||
|
|
||||||
|
public interface TenantRemovalIntegrationEventHandler extends IntegrationEventHandler {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.tenantremoval;
|
||||||
|
|
||||||
|
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
||||||
|
import gr.cite.notification.audit.AuditableAction;
|
||||||
|
import gr.cite.notification.common.JsonHandlingService;
|
||||||
|
import gr.cite.notification.common.scope.fake.FakeRequestScope;
|
||||||
|
import gr.cite.notification.errorcode.ErrorThesaurusProperties;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.EventProcessingStatus;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.InboxPrincipal;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.IntegrationEventProperties;
|
||||||
|
import gr.cite.notification.service.tenant.TenantService;
|
||||||
|
import gr.cite.tools.auditing.AuditService;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
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.MessageSource;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class TenantRemovalIntegrationEventHandlerImpl implements TenantRemovalIntegrationEventHandler {
|
||||||
|
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantRemovalIntegrationEventHandlerImpl.class));
|
||||||
|
|
||||||
|
private final JsonHandlingService jsonHandlingService;
|
||||||
|
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private final ErrorThesaurusProperties errors;
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
public TenantRemovalIntegrationEventHandlerImpl(JsonHandlingService jsonHandlingService, ApplicationContext applicationContext, ErrorThesaurusProperties errors, MessageSource messageSource) {
|
||||||
|
this.jsonHandlingService = jsonHandlingService;
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
this.errors = errors;
|
||||||
|
this.messageSource = messageSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventProcessingStatus handle(IntegrationEventProperties properties, String message) {
|
||||||
|
TenantRemovalIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(TenantRemovalIntegrationEvent.class, message);
|
||||||
|
if (event == null)
|
||||||
|
return EventProcessingStatus.Error;
|
||||||
|
|
||||||
|
EntityManager entityManager = null;
|
||||||
|
EntityTransaction transaction = null;
|
||||||
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
|
try {
|
||||||
|
CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class);
|
||||||
|
currentPrincipalResolver.push(InboxPrincipal.build(properties));
|
||||||
|
|
||||||
|
TenantRemovalConsistencyHandler tenantRemovalConsistencyHandler = this.applicationContext.getBean(TenantRemovalConsistencyHandler.class);
|
||||||
|
if (!(tenantRemovalConsistencyHandler.isConsistent(new TenantRemovalConsistencyPredicates(event.getId()))))
|
||||||
|
return EventProcessingStatus.Postponed;
|
||||||
|
|
||||||
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
entityManager = entityManagerFactory.createEntityManager();
|
||||||
|
|
||||||
|
transaction = entityManager.getTransaction();
|
||||||
|
transaction.begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
TenantService tenantService = this.applicationContext.getBean(TenantService.class);
|
||||||
|
tenantService.deleteAndSave(event.getId());
|
||||||
|
|
||||||
|
AuditService auditService = this.applicationContext.getBean(AuditService.class);
|
||||||
|
|
||||||
|
auditService.track(AuditableAction.Tenant_Delete, Map.ofEntries(
|
||||||
|
new AbstractMap.SimpleEntry<String, Object>("id", event.getId())
|
||||||
|
));
|
||||||
|
//auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
transaction.rollback();
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
currentPrincipalResolver.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} 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 null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.tenanttouched;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.TrackedEvent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class TenantTouchedIntegrationEvent extends TrackedEvent {
|
||||||
|
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.tenanttouched;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.inbox.IntegrationEventHandler;
|
||||||
|
|
||||||
|
public interface TenantTouchedIntegrationEventHandler extends IntegrationEventHandler {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.tenanttouched;
|
||||||
|
|
||||||
|
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
||||||
|
import gr.cite.notification.audit.AuditableAction;
|
||||||
|
import gr.cite.notification.common.JsonHandlingService;
|
||||||
|
import gr.cite.notification.common.scope.fake.FakeRequestScope;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.EventProcessingStatus;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.InboxPrincipal;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.IntegrationEventProperties;
|
||||||
|
import gr.cite.notification.model.persist.TenantTouchedIntegrationEventPersist;
|
||||||
|
import gr.cite.notification.service.tenant.TenantService;
|
||||||
|
import gr.cite.tools.auditing.AuditService;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
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.util.AbstractMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class TenantTouchedIntegrationEventHandlerImpl implements TenantTouchedIntegrationEventHandler {
|
||||||
|
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantTouchedIntegrationEventHandlerImpl.class));
|
||||||
|
|
||||||
|
protected final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private final JsonHandlingService jsonHandlingService;
|
||||||
|
|
||||||
|
public TenantTouchedIntegrationEventHandlerImpl(ApplicationContext applicationContext, JsonHandlingService jsonHandlingService) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
this.jsonHandlingService = jsonHandlingService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventProcessingStatus handle(IntegrationEventProperties properties, String message) {
|
||||||
|
TenantTouchedIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(TenantTouchedIntegrationEvent.class, message);
|
||||||
|
if (event == null)
|
||||||
|
return EventProcessingStatus.Error;
|
||||||
|
|
||||||
|
TenantTouchedIntegrationEventPersist model = new TenantTouchedIntegrationEventPersist();
|
||||||
|
model.setId(event.getId());
|
||||||
|
model.setCode(event.getCode());
|
||||||
|
|
||||||
|
EntityManager entityManager = null;
|
||||||
|
EntityTransaction transaction = null;
|
||||||
|
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||||
|
try {
|
||||||
|
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 {
|
||||||
|
TenantService tenantService = this.applicationContext.getBean(TenantService.class);
|
||||||
|
tenantService.persist(model, null);
|
||||||
|
|
||||||
|
AuditService auditService = this.applicationContext.getBean(AuditService.class);
|
||||||
|
|
||||||
|
auditService.track(AuditableAction.Tenant_Persist, Map.ofEntries(
|
||||||
|
new AbstractMap.SimpleEntry<String, Object>("model", model)
|
||||||
|
));
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
transaction.rollback();
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
currentPrincipalResolver.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} 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 null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.userremoval;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.inbox.ConsistencyHandler;
|
||||||
|
import gr.cite.notification.query.UserQuery;
|
||||||
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class UserRemovalConsistencyHandler implements ConsistencyHandler<UserRemovalConsistencyPredicates> {
|
||||||
|
|
||||||
|
private final QueryFactory queryFactory;
|
||||||
|
|
||||||
|
public UserRemovalConsistencyHandler(QueryFactory queryFactory) {
|
||||||
|
this.queryFactory = queryFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean isConsistent(UserRemovalConsistencyPredicates consistencyPredicates) {
|
||||||
|
long count = this.queryFactory.query(UserQuery.class).ids(consistencyPredicates.getUserId()).count();
|
||||||
|
return count != 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.userremoval;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.inbox.ConsistencyPredicates;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UserRemovalConsistencyPredicates implements ConsistencyPredicates {
|
||||||
|
|
||||||
|
private UUID userId;
|
||||||
|
|
||||||
|
public UserRemovalConsistencyPredicates(UUID userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(UUID userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.userremoval;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.TrackedEvent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UserRemovalIntegrationEvent extends TrackedEvent {
|
||||||
|
|
||||||
|
private UUID userId;
|
||||||
|
|
||||||
|
private UUID tenant;
|
||||||
|
|
||||||
|
public UUID getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(UUID userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getTenant() {
|
||||||
|
return tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenant(UUID tenant) {
|
||||||
|
this.tenant = tenant;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.userremoval;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.inbox.IntegrationEventHandler;
|
||||||
|
|
||||||
|
public interface UserRemovalIntegrationEventHandler extends IntegrationEventHandler {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.userremoval;
|
||||||
|
|
||||||
|
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
||||||
|
import gr.cite.notification.audit.AuditableAction;
|
||||||
|
import gr.cite.notification.common.JsonHandlingService;
|
||||||
|
import gr.cite.notification.common.scope.fake.FakeRequestScope;
|
||||||
|
import gr.cite.notification.common.scope.tenant.TenantScope;
|
||||||
|
import gr.cite.notification.data.TenantEntity;
|
||||||
|
import gr.cite.notification.errorcode.ErrorThesaurusProperties;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.EventProcessingStatus;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.InboxPrincipal;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.IntegrationEventProperties;
|
||||||
|
import gr.cite.notification.model.Tenant;
|
||||||
|
import gr.cite.notification.query.TenantQuery;
|
||||||
|
import gr.cite.notification.service.user.UserService;
|
||||||
|
import gr.cite.tools.auditing.AuditService;
|
||||||
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
|
import gr.cite.tools.exception.MyValidationException;
|
||||||
|
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
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.MessageSource;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class UserRemovalIntegrationEventHandlerImpl implements UserRemovalIntegrationEventHandler {
|
||||||
|
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserRemovalIntegrationEventHandlerImpl.class));
|
||||||
|
|
||||||
|
private final JsonHandlingService jsonHandlingService;
|
||||||
|
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private final ErrorThesaurusProperties errors;
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
public UserRemovalIntegrationEventHandlerImpl(
|
||||||
|
JsonHandlingService jsonHandlingService,
|
||||||
|
ApplicationContext applicationContext,
|
||||||
|
ErrorThesaurusProperties errors,
|
||||||
|
MessageSource messageSource
|
||||||
|
) {
|
||||||
|
this.jsonHandlingService = jsonHandlingService;
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
this.errors = errors;
|
||||||
|
this.messageSource = messageSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventProcessingStatus handle(IntegrationEventProperties properties, String message) {
|
||||||
|
UserRemovalIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(UserRemovalIntegrationEvent.class, message);
|
||||||
|
if (event == null)
|
||||||
|
return EventProcessingStatus.Error;
|
||||||
|
if (event.getUserId() == null)
|
||||||
|
throw new MyValidationException(this.errors.getModelValidation().getCode(), "userId", messageSource.getMessage("Validation_Required", new Object[]{"userId"}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class);
|
||||||
|
currentPrincipalResolver.push(InboxPrincipal.build(properties));
|
||||||
|
|
||||||
|
UserRemovalConsistencyHandler userRemovalConsistencyHandler = this.applicationContext.getBean(UserRemovalConsistencyHandler.class);
|
||||||
|
if (!(userRemovalConsistencyHandler.isConsistent(new UserRemovalConsistencyPredicates(event.getUserId()))))
|
||||||
|
return EventProcessingStatus.Postponed;
|
||||||
|
|
||||||
|
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||||
|
entityManager = entityManagerFactory.createEntityManager();
|
||||||
|
|
||||||
|
transaction = entityManager.getTransaction();
|
||||||
|
transaction.begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
UserService userService = this.applicationContext.getBean(UserService.class);
|
||||||
|
userService.deleteAndSave(event.getUserId());
|
||||||
|
|
||||||
|
AuditService auditService = this.applicationContext.getBean(AuditService.class);
|
||||||
|
|
||||||
|
auditService.track(AuditableAction.User_Delete, Map.ofEntries(
|
||||||
|
new AbstractMap.SimpleEntry<String, Object>("id", event.getUserId())
|
||||||
|
));
|
||||||
|
//auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
transaction.rollback();
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
currentPrincipalResolver.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} 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 null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.usertouched;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.TrackedEvent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UserTouchedIntegrationEvent extends TrackedEvent {
|
||||||
|
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
private UUID tenant;
|
||||||
|
|
||||||
|
private String firstName;
|
||||||
|
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getTenant() {
|
||||||
|
return tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenant(UUID tenant) {
|
||||||
|
this.tenant = tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.usertouched;
|
||||||
|
|
||||||
|
import gr.cite.notification.integrationevent.inbox.IntegrationEventHandler;
|
||||||
|
|
||||||
|
public interface UserTouchedIntegrationEventHandler extends IntegrationEventHandler {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
package gr.cite.notification.integrationevent.inbox.usertouched;
|
||||||
|
|
||||||
|
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
||||||
|
import gr.cite.notification.audit.AuditableAction;
|
||||||
|
import gr.cite.notification.common.JsonHandlingService;
|
||||||
|
import gr.cite.notification.common.scope.fake.FakeRequestScope;
|
||||||
|
import gr.cite.notification.common.scope.tenant.TenantScope;
|
||||||
|
import gr.cite.notification.data.TenantEntity;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.EventProcessingStatus;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.InboxPrincipal;
|
||||||
|
import gr.cite.notification.integrationevent.inbox.IntegrationEventProperties;
|
||||||
|
import gr.cite.notification.model.Tenant;
|
||||||
|
import gr.cite.notification.model.persist.UserTouchedIntegrationEventPersist;
|
||||||
|
import gr.cite.notification.query.TenantQuery;
|
||||||
|
import gr.cite.notification.service.user.UserService;
|
||||||
|
import gr.cite.tools.auditing.AuditService;
|
||||||
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
|
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
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.util.AbstractMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class UserTouchedIntegrationEventHandlerImpl implements UserTouchedIntegrationEventHandler {
|
||||||
|
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserTouchedIntegrationEventHandlerImpl.class));
|
||||||
|
|
||||||
|
protected final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private final JsonHandlingService jsonHandlingService;
|
||||||
|
|
||||||
|
public UserTouchedIntegrationEventHandlerImpl(
|
||||||
|
JsonHandlingService jsonHandlingService,
|
||||||
|
ApplicationContext applicationContext
|
||||||
|
) {
|
||||||
|
this.jsonHandlingService = jsonHandlingService;
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventProcessingStatus handle(IntegrationEventProperties properties, String message) {
|
||||||
|
UserTouchedIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(UserTouchedIntegrationEvent.class, message);
|
||||||
|
if (event == null)
|
||||||
|
return EventProcessingStatus.Error;
|
||||||
|
|
||||||
|
UserTouchedIntegrationEventPersist model = new UserTouchedIntegrationEventPersist();
|
||||||
|
model.setId(event.getId());
|
||||||
|
model.setFirstName(event.getFirstName());
|
||||||
|
model.setLastName(event.getLastName());
|
||||||
|
|
||||||
|
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 {
|
||||||
|
UserService userService = this.applicationContext.getBean(UserService.class);
|
||||||
|
userService.persist(model, null);
|
||||||
|
|
||||||
|
AuditService auditService = this.applicationContext.getBean(AuditService.class);
|
||||||
|
|
||||||
|
auditService.track(AuditableAction.User_Persist, Map.ofEntries(
|
||||||
|
new AbstractMap.SimpleEntry<String, Object>("model", model)
|
||||||
|
));
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
transaction.rollback();
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
currentPrincipalResolver.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
} 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 null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package gr.cite.notification.integrationevent.outbox;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@Validated
|
||||||
|
@ConfigurationProperties(prefix = "queue.task.publisher.options")
|
||||||
|
public class OutboxProperties {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String exchange;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String tenantTouchTopic;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String tenantRemovalTopic;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String tenantReactivationTopic;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String tenantUserInviteTopic;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String notifyTopic;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String forgetMeCompletedTopic;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String whatYouKnowAboutMeCompletedTopic;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String generateFileTopic;
|
||||||
|
|
||||||
|
public OutboxProperties(String exchange,
|
||||||
|
String tenantTouchTopic,
|
||||||
|
String tenantRemovalTopic,
|
||||||
|
String tenantReactivationTopic,
|
||||||
|
String tenantUserInviteTopic,
|
||||||
|
String notifyTopic,
|
||||||
|
String forgetMeCompletedTopic,
|
||||||
|
String whatYouKnowAboutMeCompletedTopic,
|
||||||
|
String generateFileTopic
|
||||||
|
) {
|
||||||
|
this.exchange = exchange;
|
||||||
|
this.tenantTouchTopic = tenantTouchTopic;
|
||||||
|
this.tenantRemovalTopic = tenantRemovalTopic;
|
||||||
|
this.tenantReactivationTopic = tenantReactivationTopic;
|
||||||
|
this.tenantUserInviteTopic = tenantUserInviteTopic;
|
||||||
|
this.notifyTopic = notifyTopic;
|
||||||
|
this.forgetMeCompletedTopic = forgetMeCompletedTopic;
|
||||||
|
this.whatYouKnowAboutMeCompletedTopic = whatYouKnowAboutMeCompletedTopic;
|
||||||
|
this.generateFileTopic = generateFileTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExchange() {
|
||||||
|
return exchange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTenantTouchTopic() {
|
||||||
|
return tenantTouchTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTenantRemovalTopic() {
|
||||||
|
return tenantRemovalTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTenantReactivationTopic() {
|
||||||
|
return tenantReactivationTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTenantUserInviteTopic() {
|
||||||
|
return tenantUserInviteTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNotifyTopic() {
|
||||||
|
return notifyTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getForgetMeCompletedTopic() {
|
||||||
|
return forgetMeCompletedTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWhatYouKnowAboutMeCompletedTopic() {
|
||||||
|
return whatYouKnowAboutMeCompletedTopic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGenerateFileTopic() {
|
||||||
|
return generateFileTopic;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package gr.cite.notification.model.persist;
|
||||||
|
|
||||||
|
import gr.cite.notification.common.validation.ValidId;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class TenantTouchedIntegrationEventPersist {
|
||||||
|
|
||||||
|
@ValidId(message = "{validation.invalidid}")
|
||||||
|
@NotNull(message = "{validation.empty}")
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@NotNull(message = "{validation.empty}")
|
||||||
|
@NotEmpty(message = "{validation.empty}")
|
||||||
|
@Size(max = 50, message = "{validation.largerthanmax}")
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -35,6 +35,8 @@ public class NotificationQuery extends QueryBase<NotificationEntity> {
|
||||||
private List<NotificationTrackingState> trackingState;
|
private List<NotificationTrackingState> trackingState;
|
||||||
|
|
||||||
private List<NotificationTrackingProcess> trackingProgress;
|
private List<NotificationTrackingProcess> trackingProgress;
|
||||||
|
|
||||||
|
private Collection<UUID> userIds;
|
||||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||||
|
|
||||||
public NotificationQuery ids(UUID value) {
|
public NotificationQuery ids(UUID value) {
|
||||||
|
@ -172,6 +174,21 @@ public class NotificationQuery extends QueryBase<NotificationEntity> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NotificationQuery userIds(UUID value) {
|
||||||
|
this.userIds = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotificationQuery userIds(UUID... value) {
|
||||||
|
this.userIds = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotificationQuery userIds(Collection<UUID> values) {
|
||||||
|
this.userIds = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public NotificationQuery ordering(Ordering ordering) {
|
public NotificationQuery ordering(Ordering ordering) {
|
||||||
this.setOrder(ordering);
|
this.setOrder(ordering);
|
||||||
return this;
|
return this;
|
||||||
|
@ -246,6 +263,10 @@ public class NotificationQuery extends QueryBase<NotificationEntity> {
|
||||||
predicates.add(queryContext.Root.get(NotificationEntity.Field._trackingProcess).in(trackingProgress));
|
predicates.add(queryContext.Root.get(NotificationEntity.Field._trackingProcess).in(trackingProgress));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.userIds != null) {
|
||||||
|
predicates.add(queryContext.Root.get(NotificationEntity.Field._userId).in(userIds));
|
||||||
|
}
|
||||||
|
|
||||||
if (predicates.size() > 0) {
|
if (predicates.size() > 0) {
|
||||||
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
|
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
|
||||||
return queryContext.CriteriaBuilder.and(predicatesArray);
|
return queryContext.CriteriaBuilder.and(predicatesArray);
|
||||||
|
|
|
@ -24,6 +24,7 @@ public class NotificationLookup extends Lookup {
|
||||||
private Instant createdAfter;
|
private Instant createdAfter;
|
||||||
private List<NotificationTrackingState> trackingState;
|
private List<NotificationTrackingState> trackingState;
|
||||||
private List<NotificationTrackingProcess> trackingProcess;
|
private List<NotificationTrackingProcess> trackingProcess;
|
||||||
|
private List<UUID> userIds;
|
||||||
|
|
||||||
|
|
||||||
public List<IsActive> getIsActive() {
|
public List<IsActive> getIsActive() {
|
||||||
|
@ -122,6 +123,14 @@ public class NotificationLookup extends Lookup {
|
||||||
this.trackingProcess = trackingProcess;
|
this.trackingProcess = trackingProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<UUID> getUserIds() {
|
||||||
|
return userIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserIds(List<UUID> userIds) {
|
||||||
|
this.userIds = userIds;
|
||||||
|
}
|
||||||
|
|
||||||
public NotificationQuery enrich(QueryFactory queryFactory) {
|
public NotificationQuery enrich(QueryFactory queryFactory) {
|
||||||
NotificationQuery query = queryFactory.query(NotificationQuery.class);
|
NotificationQuery query = queryFactory.query(NotificationQuery.class);
|
||||||
if (this.isActive != null) query.isActive(this.isActive);
|
if (this.isActive != null) query.isActive(this.isActive);
|
||||||
|
@ -136,6 +145,7 @@ public class NotificationLookup extends Lookup {
|
||||||
if (this.type != null) query.type(this.type);
|
if (this.type != null) query.type(this.type);
|
||||||
if (this.trackingProcess != null) query.trackingProgress(this.trackingProcess);
|
if (this.trackingProcess != null) query.trackingProgress(this.trackingProcess);
|
||||||
if (this.trackingState != null) query.trackingState(this.trackingState);
|
if (this.trackingState != null) query.trackingState(this.trackingState);
|
||||||
|
if (this.userIds != null) query.userIds(this.userIds);
|
||||||
|
|
||||||
this.enrichCommon(query);
|
this.enrichCommon(query);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package gr.cite.notification.service.tenant;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import gr.cite.notification.model.Tenant;
|
||||||
|
import gr.cite.notification.model.User;
|
||||||
|
import gr.cite.notification.model.persist.TenantTouchedIntegrationEventPersist;
|
||||||
|
import gr.cite.notification.model.persist.UserTouchedIntegrationEventPersist;
|
||||||
|
import gr.cite.tools.exception.MyApplicationException;
|
||||||
|
import gr.cite.tools.exception.MyForbiddenException;
|
||||||
|
import gr.cite.tools.exception.MyNotFoundException;
|
||||||
|
import gr.cite.tools.exception.MyValidationException;
|
||||||
|
import gr.cite.tools.fieldset.FieldSet;
|
||||||
|
|
||||||
|
import javax.management.InvalidApplicationException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface TenantService {
|
||||||
|
|
||||||
|
Tenant persist(TenantTouchedIntegrationEventPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException;
|
||||||
|
|
||||||
|
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package gr.cite.notification.service.tenant;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||||
|
import gr.cite.notification.authorization.Permission;
|
||||||
|
import gr.cite.notification.model.Tenant;
|
||||||
|
import gr.cite.notification.model.deleter.TenantDeleter;
|
||||||
|
import gr.cite.notification.model.deleter.UserDeleter;
|
||||||
|
import gr.cite.notification.model.persist.TenantTouchedIntegrationEventPersist;
|
||||||
|
import gr.cite.notification.service.user.UserServiceImpl;
|
||||||
|
import gr.cite.tools.data.deleter.DeleterFactory;
|
||||||
|
import gr.cite.tools.exception.MyApplicationException;
|
||||||
|
import gr.cite.tools.exception.MyForbiddenException;
|
||||||
|
import gr.cite.tools.exception.MyNotFoundException;
|
||||||
|
import gr.cite.tools.exception.MyValidationException;
|
||||||
|
import gr.cite.tools.fieldset.FieldSet;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.management.InvalidApplicationException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class TenantServiceImpl implements TenantService {
|
||||||
|
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantServiceImpl.class));
|
||||||
|
|
||||||
|
private final AuthorizationService authorizationService;
|
||||||
|
|
||||||
|
private final DeleterFactory deleterFactory;
|
||||||
|
|
||||||
|
public TenantServiceImpl(AuthorizationService authorizationService, DeleterFactory deleterFactory) {
|
||||||
|
this.authorizationService = authorizationService;
|
||||||
|
this.deleterFactory = deleterFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tenant persist(TenantTouchedIntegrationEventPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
|
||||||
|
logger.debug("deleting Tenant: {}", id);
|
||||||
|
|
||||||
|
this.authorizationService.authorizeForce(Permission.DeleteTenant);
|
||||||
|
|
||||||
|
this.deleterFactory.deleter(TenantDeleter.class).deleteAndSaveByIds(List.of(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package gr.cite.notification.service.user;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import gr.cite.notification.model.User;
|
||||||
|
import gr.cite.notification.model.persist.UserTouchedIntegrationEventPersist;
|
||||||
|
import gr.cite.tools.exception.MyApplicationException;
|
||||||
|
import gr.cite.tools.exception.MyForbiddenException;
|
||||||
|
import gr.cite.tools.exception.MyNotFoundException;
|
||||||
|
import gr.cite.tools.exception.MyValidationException;
|
||||||
|
import gr.cite.tools.fieldset.FieldSet;
|
||||||
|
|
||||||
|
import javax.management.InvalidApplicationException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface UserService {
|
||||||
|
|
||||||
|
User persist(UserTouchedIntegrationEventPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException;
|
||||||
|
|
||||||
|
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package gr.cite.notification.service.user;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||||
|
import gr.cite.notification.authorization.Permission;
|
||||||
|
import gr.cite.notification.model.User;
|
||||||
|
import gr.cite.notification.model.deleter.UserDeleter;
|
||||||
|
import gr.cite.notification.model.persist.UserTouchedIntegrationEventPersist;
|
||||||
|
import gr.cite.tools.data.deleter.DeleterFactory;
|
||||||
|
import gr.cite.tools.exception.MyApplicationException;
|
||||||
|
import gr.cite.tools.exception.MyForbiddenException;
|
||||||
|
import gr.cite.tools.exception.MyNotFoundException;
|
||||||
|
import gr.cite.tools.exception.MyValidationException;
|
||||||
|
import gr.cite.tools.fieldset.FieldSet;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.management.InvalidApplicationException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserServiceImpl implements UserService {
|
||||||
|
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserServiceImpl.class));
|
||||||
|
|
||||||
|
private final AuthorizationService authorizationService;
|
||||||
|
|
||||||
|
private final DeleterFactory deleterFactory;
|
||||||
|
|
||||||
|
public UserServiceImpl(AuthorizationService authorizationService, DeleterFactory deleterFactory) {
|
||||||
|
this.authorizationService = authorizationService;
|
||||||
|
this.deleterFactory = deleterFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User persist(UserTouchedIntegrationEventPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JsonProcessingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
|
||||||
|
logger.debug("deleting User: {}", id);
|
||||||
|
|
||||||
|
this.authorizationService.authorizeForce(Permission.DeleteUser);
|
||||||
|
|
||||||
|
this.deleterFactory.deleter(UserDeleter.class).deleteAndSaveByIds(List.of(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,6 +29,24 @@
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<!-- https://mvnrepository.com/artifact/jakarta.annotation/jakarta.annotation-api -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.annotation</groupId>
|
||||||
|
<artifactId>jakarta.annotation-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/jakarta.validation/validation-api -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.validation</groupId>
|
||||||
|
<artifactId>jakarta.validation-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.persistence</groupId>
|
||||||
|
<artifactId>jakarta.persistence-api</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>gr.cite</groupId>
|
<groupId>gr.cite</groupId>
|
||||||
<artifactId>queue-inbox</artifactId>
|
<artifactId>queue-inbox</artifactId>
|
||||||
|
@ -39,6 +57,12 @@
|
||||||
<artifactId>queue-outbox</artifactId>
|
<artifactId>queue-outbox</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>gr.cite</groupId>
|
||||||
|
<artifactId>rabbitmq-core</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|
|
@ -17,6 +17,7 @@ export class NotificationLookup extends Lookup implements NotificationFilter {
|
||||||
contactType: NotificationContactType[];
|
contactType: NotificationContactType[];
|
||||||
trackingState: NotificationTrackingState[];
|
trackingState: NotificationTrackingState[];
|
||||||
trackingProcess: NotificationTrackingProcess[];
|
trackingProcess: NotificationTrackingProcess[];
|
||||||
|
userIds: Guid[];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
@ -33,4 +34,5 @@ export interface NotificationFilter {
|
||||||
contactType: NotificationContactType[];
|
contactType: NotificationContactType[];
|
||||||
trackingState: NotificationTrackingState[];
|
trackingState: NotificationTrackingState[];
|
||||||
trackingProcess: NotificationTrackingProcess[];
|
trackingProcess: NotificationTrackingProcess[];
|
||||||
|
userIds: Guid[];
|
||||||
}
|
}
|
|
@ -39,9 +39,9 @@
|
||||||
|
|
||||||
<div class="d-flex align-items-center p-3 gap-1-rem">
|
<div class="d-flex align-items-center p-3 gap-1-rem">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<ng-container *ngIf="isColumnSelected('name')">
|
<ng-container *ngIf="isColumnSelected('code')">
|
||||||
<a class="buttonLinkClass" [routerLink]="'./' + item?.id" class="col-12"
|
<a class="buttonLinkClass" [routerLink]="'./' + item?.id" class="col-12"
|
||||||
(click)="$event.stopPropagation()">{{item?.name | nullifyValue}}</a>
|
(click)="$event.stopPropagation()">{{item?.code | nullifyValue}}</a>
|
||||||
<br />
|
<br />
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,14 @@
|
||||||
</span>
|
</span>
|
||||||
<br>
|
<br>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
<ng-container *ngIf="isColumnSelected('createdAt')">
|
||||||
|
<span class="col-12">
|
||||||
|
{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.CREATED-AT' | translate}}:
|
||||||
|
<small>
|
||||||
|
{{item?.createdAt | dateTimeFormatter : 'short' | nullifyValue}}
|
||||||
|
</small>
|
||||||
|
</span>
|
||||||
|
</ng-container>
|
||||||
<ng-container *ngIf="isColumnSelected('updatedAt')">
|
<ng-container *ngIf="isColumnSelected('updatedAt')">
|
||||||
<span class="col-12">
|
<span class="col-12">
|
||||||
{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.UPDATED-AT' | translate}}:
|
{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FIELDS.UPDATED-AT' | translate}}:
|
||||||
|
|
|
@ -20,6 +20,14 @@
|
||||||
{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.IS-ACTIVE' | translate}}
|
{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.IS-ACTIVE' | translate}}
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<mat-form-field class="col-12">
|
||||||
|
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.USERS' | translate}}</mat-label>
|
||||||
|
<app-multiple-auto-complete [(ngModel)]="internalFilters.userIds" [hidePlaceholder]="true" [separatorKeysCodes]="separatorKeysCodes" [configuration]="userAutoCompleteConfiguration">
|
||||||
|
</app-multiple-auto-complete>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.NOTIFICATION-TYPE' | translate}}
|
<mat-label>{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.NOTIFICATION-TYPE' | translate}}
|
||||||
<mat-select multiple [(ngModel)]="internalFilters.type">
|
<mat-select multiple [(ngModel)]="internalFilters.type">
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { COMMA, ENTER } from '@angular/cdk/keycodes';
|
||||||
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
|
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
|
||||||
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
||||||
import { NotificationContactType } from '@app/core/common/enum/notification-contact-type';
|
import { NotificationContactType } from '@app/core/common/enum/notification-contact-type';
|
||||||
|
@ -6,8 +7,11 @@ import { NotificationTrackingProcess } from '@app/core/common/enum/notification-
|
||||||
import { NotificationTrackingState } from '@app/core/common/enum/notification-tracking-state';
|
import { NotificationTrackingState } from '@app/core/common/enum/notification-tracking-state';
|
||||||
import { NotificationType } from '@app/core/common/enum/notification-type';
|
import { NotificationType } from '@app/core/common/enum/notification-type';
|
||||||
import { NotificationFilter } from '@app/core/query/notification.lookup';
|
import { NotificationFilter } from '@app/core/query/notification.lookup';
|
||||||
|
import { UserService } from '@app/core/services/user/user.service';
|
||||||
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
|
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
|
||||||
|
import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration';
|
||||||
import { BaseComponent } from '@common/base/base.component';
|
import { BaseComponent } from '@common/base/base.component';
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
import { nameof } from 'ts-simple-nameof';
|
import { nameof } from 'ts-simple-nameof';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -24,6 +28,9 @@ export class NotificationListingFiltersComponent extends BaseComponent implement
|
||||||
notificationTrackingStateEnumValues = this.enumUtils.getEnumValues<NotificationTrackingState>(NotificationTrackingState);
|
notificationTrackingStateEnumValues = this.enumUtils.getEnumValues<NotificationTrackingState>(NotificationTrackingState);
|
||||||
notificationTrackingProcessEnumValues = this.enumUtils.getEnumValues<NotificationTrackingProcess>(NotificationTrackingProcess);
|
notificationTrackingProcessEnumValues = this.enumUtils.getEnumValues<NotificationTrackingProcess>(NotificationTrackingProcess);
|
||||||
notificationTypeEnumValues = this.enumUtils.getEnumValues<NotificationType>(NotificationType);
|
notificationTypeEnumValues = this.enumUtils.getEnumValues<NotificationType>(NotificationType);
|
||||||
|
userAutoCompleteConfiguration: MultipleAutoCompleteConfiguration;
|
||||||
|
|
||||||
|
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
|
||||||
|
|
||||||
// * State
|
// * State
|
||||||
internalFilters: NotificationListingFilters = this._getEmptyFilters();
|
internalFilters: NotificationListingFilters = this._getEmptyFilters();
|
||||||
|
@ -31,9 +38,11 @@ export class NotificationListingFiltersComponent extends BaseComponent implement
|
||||||
protected appliedFilterCount: number = 0;
|
protected appliedFilterCount: number = 0;
|
||||||
constructor(
|
constructor(
|
||||||
public enumUtils: EnumUtils,
|
public enumUtils: EnumUtils,
|
||||||
|
private userService: UserService,
|
||||||
) { super(); }
|
) { super(); }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.userAutoCompleteConfiguration = this.userService.multipleAutocompleteConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
|
@ -55,7 +64,7 @@ export class NotificationListingFiltersComponent extends BaseComponent implement
|
||||||
}
|
}
|
||||||
|
|
||||||
protected applyFilters(): void {
|
protected applyFilters(): void {
|
||||||
const { isActive, type, notifyState, notifiedWith, contactType, trackingState, trackingProcess } = this.internalFilters ?? {}
|
const { isActive, type, notifyState, notifiedWith, contactType, trackingState, trackingProcess, userIds } = this.internalFilters ?? {}
|
||||||
this.filterChange.emit({
|
this.filterChange.emit({
|
||||||
...this.filter,
|
...this.filter,
|
||||||
isActive: isActive ? [IsActive.Active] : [IsActive.Inactive],
|
isActive: isActive ? [IsActive.Active] : [IsActive.Inactive],
|
||||||
|
@ -64,7 +73,8 @@ export class NotificationListingFiltersComponent extends BaseComponent implement
|
||||||
notifiedWith,
|
notifiedWith,
|
||||||
contactType,
|
contactType,
|
||||||
trackingState,
|
trackingState,
|
||||||
trackingProcess
|
trackingProcess,
|
||||||
|
userIds
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +84,7 @@ export class NotificationListingFiltersComponent extends BaseComponent implement
|
||||||
return this._getEmptyFilters();
|
return this._getEmptyFilters();
|
||||||
}
|
}
|
||||||
|
|
||||||
let { isActive, type, notifyState, notifiedWith, contactType, trackingState, trackingProcess } = inputFilter;
|
let { isActive, type, notifyState, notifiedWith, contactType, trackingState, trackingProcess, userIds } = inputFilter;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isActive: (isActive ?? [])?.includes(IsActive.Active) || !isActive?.length,
|
isActive: (isActive ?? [])?.includes(IsActive.Active) || !isActive?.length,
|
||||||
|
@ -83,7 +93,8 @@ export class NotificationListingFiltersComponent extends BaseComponent implement
|
||||||
notifiedWith: notifiedWith,
|
notifiedWith: notifiedWith,
|
||||||
contactType: contactType,
|
contactType: contactType,
|
||||||
trackingState: trackingState,
|
trackingState: trackingState,
|
||||||
trackingProcess: trackingProcess
|
trackingProcess: trackingProcess,
|
||||||
|
userIds: userIds
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -96,7 +107,8 @@ export class NotificationListingFiltersComponent extends BaseComponent implement
|
||||||
notifiedWith: null,
|
notifiedWith: null,
|
||||||
contactType: null,
|
contactType: null,
|
||||||
trackingState: null,
|
trackingState: null,
|
||||||
trackingProcess: null
|
trackingProcess: null,
|
||||||
|
userIds: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,4 +133,5 @@ interface NotificationListingFilters {
|
||||||
contactType: NotificationContactType[];
|
contactType: NotificationContactType[];
|
||||||
trackingState: NotificationTrackingState[];
|
trackingState: NotificationTrackingState[];
|
||||||
trackingProcess: NotificationTrackingProcess[];
|
trackingProcess: NotificationTrackingProcess[];
|
||||||
|
userIds: Guid[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
<app-hybrid-listing [rows]="gridRows" [columns]="gridColumns" [visibleColumns]="visibleColumns"
|
<app-hybrid-listing [rows]="gridRows" [columns]="gridColumns" [visibleColumns]="visibleColumns"
|
||||||
[count]="totalElements" [offset]="currentPageNumber" [limit]="lookup.page.size"
|
[count]="totalElements" [offset]="currentPageNumber" [limit]="lookup.page.size"
|
||||||
[defaultSort]="lookup.order?.items" [externalSorting]="true" (rowActivated)="onRowActivated($event)"
|
[defaultSort]="lookup.order?.items" [externalSorting]="true"
|
||||||
(pageLoad)="alterPage($event)" (columnSort)="onColumnSort($event)"
|
(pageLoad)="alterPage($event)" (columnSort)="onColumnSort($event)"
|
||||||
(columnsChanged)="onColumnsChanged($event)" [listItemTemplate]="listItemTemplate">
|
(columnsChanged)="onColumnsChanged($event)" [listItemTemplate]="listItemTemplate">
|
||||||
|
|
||||||
|
@ -31,43 +31,47 @@
|
||||||
|
|
||||||
<div class="d-flex align-items-center p-3 gap-1-rem">
|
<div class="d-flex align-items-center p-3 gap-1-rem">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<ng-container *ngIf="isColumnSelected('name')">
|
<ng-container *ngIf="isColumnSelected('type')">
|
||||||
<a class="buttonLinkClass" [routerLink]="'./' + item?.id" class="col-12"
|
|
||||||
(click)="$event.stopPropagation()">{{item?.name | nullifyValue}}</a>
|
|
||||||
<br />
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="isColumnSelected('notificationType')">
|
|
||||||
<span class="col-12">
|
<span class="col-12">
|
||||||
{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFICATION-TYPE' | translate}}:
|
{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFICATION-TYPE' | translate}}:
|
||||||
<small>
|
<small>
|
||||||
{{enumUtils.toNotificationTypeString(item.notificationType) | nullifyValue}}
|
{{enumUtils.toNotificationTypeString(item.type) | nullifyValue}}
|
||||||
</small>
|
</small>
|
||||||
</span>
|
</span>
|
||||||
<br>
|
<br>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="isColumnSelected('kind')">
|
<ng-container *ngIf="isColumnSelected('contactTypeHint')">
|
||||||
<span class="col-12">
|
<span class="col-12">
|
||||||
{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.KIND' | translate}}:
|
{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.CONTACT-TYPE' | translate}}:
|
||||||
<small>
|
<small>
|
||||||
{{enumUtils.toNotificationTemplateKindString(item.kind) | nullifyValue}}
|
{{enumUtils.toNotificationContactTypeString(item.contactTypeHint) | nullifyValue}}
|
||||||
</small>
|
</small>
|
||||||
</span>
|
</span>
|
||||||
<br>
|
<br>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="isColumnSelected('channel')">
|
<ng-container *ngIf="isColumnSelected('notifyState')">
|
||||||
<span class="col-12">
|
<span class="col-12">
|
||||||
{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.CHANNEL' | translate}}:
|
{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFY-STATE' | translate}}:
|
||||||
<small>
|
<small>
|
||||||
{{enumUtils.toNotificationTemplateChannelString(item.channel) | nullifyValue}}
|
{{enumUtils.toNotificationNotifyStateString(item.notifyState) | nullifyValue}}
|
||||||
</small>
|
</small>
|
||||||
</span>
|
</span>
|
||||||
<br>
|
<br>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="isColumnSelected('updatedAt')">
|
<ng-container *ngIf="isColumnSelected('notifiedAt')">
|
||||||
<span class="col-12">
|
<span class="col-12">
|
||||||
{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.UPDATED-AT' | translate}}:
|
{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFIED-AT' | translate}}:
|
||||||
<small>
|
<small>
|
||||||
{{item?.updatedAt | dateTimeFormatter : 'short' | nullifyValue}}
|
{{item?.notifiedAt | dateTimeFormatter : 'short' | nullifyValue}}
|
||||||
|
</small>
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngIf="isColumnSelected('createdAt')">
|
||||||
|
<span class="col-12">
|
||||||
|
{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.CREATED-AT' | translate}}:
|
||||||
|
<small>
|
||||||
|
{{item?.createdAt | dateTimeFormatter : 'short' | nullifyValue}}
|
||||||
</small>
|
</small>
|
||||||
</span>
|
</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
|
@ -50,6 +50,8 @@ export class NotificationListingComponent extends BaseListingComponent<Notificat
|
||||||
nameof<Notification>(x => x.notifyState),
|
nameof<Notification>(x => x.notifyState),
|
||||||
nameof<Notification>(x => x.notifiedWith),
|
nameof<Notification>(x => x.notifiedWith),
|
||||||
nameof<Notification>(x => x.notifiedAt),
|
nameof<Notification>(x => x.notifiedAt),
|
||||||
|
nameof<Notification>(x => x.user.id),
|
||||||
|
nameof<Notification>(x => x.user.name),
|
||||||
nameof<Notification>(x => x.createdAt),
|
nameof<Notification>(x => x.createdAt),
|
||||||
nameof<Notification>(x => x.updatedAt),
|
nameof<Notification>(x => x.updatedAt),
|
||||||
nameof<Notification>(x => x.hash),
|
nameof<Notification>(x => x.hash),
|
||||||
|
@ -125,7 +127,7 @@ export class NotificationListingComponent extends BaseListingComponent<Notificat
|
||||||
prop: nameof<Notification>(x => x.notifiedAt),
|
prop: nameof<Notification>(x => x.notifiedAt),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFIED-AT',
|
languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.NOTIFIED-AT',
|
||||||
// pipe: this.pipeService.getPipe<NotificationContactTypePipe>(NotificationContactTypePipe)
|
pipe: this.pipeService.getPipe<DataTableDateTimeFormatPipe>(DataTableDateTimeFormatPipe).withFormat('short')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
prop: nameof<Notification>(x => x.trackingState),
|
prop: nameof<Notification>(x => x.trackingState),
|
||||||
|
@ -133,6 +135,11 @@ export class NotificationListingComponent extends BaseListingComponent<Notificat
|
||||||
languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.TRACKING-STATE',
|
languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.TRACKING-STATE',
|
||||||
pipe: this.pipeService.getPipe<NotificationTrackingStatePipe>(NotificationTrackingStatePipe)
|
pipe: this.pipeService.getPipe<NotificationTrackingStatePipe>(NotificationTrackingStatePipe)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
prop: nameof<Notification>(x => x.user.name),
|
||||||
|
sortable: true,
|
||||||
|
languageName: 'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FIELDS.USER',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
prop: nameof<Notification>(x => x.trackingProcess),
|
prop: nameof<Notification>(x => x.trackingProcess),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="row description-template-type-listing">
|
<div class="row reference-type-listing">
|
||||||
<div class="col-md-8 offset-md-2">
|
<div class="col-md-8 offset-md-2">
|
||||||
|
|
||||||
<div class="row mb-4 mt-3">
|
<div class="row mb-4 mt-3">
|
||||||
|
@ -49,12 +49,13 @@
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="isColumnSelected('code')">
|
<ng-container *ngIf="isColumnSelected('code')">
|
||||||
<div class="col-auto">
|
<span class="col-12">
|
||||||
<div class="status-chip"
|
{{'REFERENCE-TYPE-LISTING.FIELDS.CODE' | translate}}:
|
||||||
[ngClass]="{'status-chip-finalized': item.status === descriptionTemplateTypeStatuses.Finalized, 'status-chip-draft' : item.status === descriptionTemplateTypeStatuses.Draft}">
|
<small>
|
||||||
{{enumUtils.toDescriptionTemplateTypeStatusString(item.status) | nullifyValue}}
|
{{item?.code | nullifyValue}}
|
||||||
</div>
|
</small>
|
||||||
</div>
|
</span>
|
||||||
|
<br>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="isColumnSelected('createdAt')">
|
<ng-container *ngIf="isColumnSelected('createdAt')">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.description-template-type-listing {
|
.reference-type-listing {
|
||||||
margin-top: 1.3rem;
|
margin-top: 1.3rem;
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
margin-right: 2rem;
|
margin-right: 2rem;
|
||||||
|
|
|
@ -39,12 +39,42 @@
|
||||||
|
|
||||||
<div class="d-flex align-items-center p-3 gap-1-rem">
|
<div class="d-flex align-items-center p-3 gap-1-rem">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<ng-container *ngIf="isColumnSelected('name')">
|
<ng-container *ngIf="isColumnSelected('label')">
|
||||||
<a class="buttonLinkClass" [routerLink]="'./' + item?.id" class="col-12"
|
<a class="buttonLinkClass" [routerLink]="'./' + item?.id" class="col-12"
|
||||||
(click)="$event.stopPropagation()">{{item?.name | nullifyValue}}</a>
|
(click)="$event.stopPropagation()">{{item?.label | nullifyValue}}</a>
|
||||||
<br />
|
<br />
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="isColumnSelected('source')">
|
||||||
|
<span class="col-12">
|
||||||
|
{{'REFERENCE-LISTING.FIELDS.SOURCE' | translate}}:
|
||||||
|
<small>
|
||||||
|
{{item.source}}
|
||||||
|
</small>
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="isColumnSelected('sourceType')">
|
||||||
|
<span class="col-12">
|
||||||
|
{{'REFERENCE-LISTING.FIELDS.SOURCE-TYPE' | translate}}:
|
||||||
|
<small>
|
||||||
|
{{enumUtils.toReferenceTypeSourceTypeString(item.sourceType) | nullifyValue}}
|
||||||
|
</small>
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="isColumnSelected('type')">
|
||||||
|
<span class="col-12">
|
||||||
|
{{'REFERENCE-LISTING.FIELDS.TYPE' | translate}}:
|
||||||
|
<small>
|
||||||
|
{{enumUtils.toReferenceTypeString(item.type) | nullifyValue}}
|
||||||
|
</small>
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="isColumnSelected('createdAt')">
|
<ng-container *ngIf="isColumnSelected('createdAt')">
|
||||||
<span class="col-12">
|
<span class="col-12">
|
||||||
{{'REFERENCE-LISTING.FIELDS.CREATED-AT' | translate}}:
|
{{'REFERENCE-LISTING.FIELDS.CREATED-AT' | translate}}:
|
||||||
|
|
|
@ -45,13 +45,14 @@
|
||||||
<br />
|
<br />
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="isColumnSelected('status')">
|
<ng-container *ngIf="isColumnSelected('code')">
|
||||||
<div class="col-auto">
|
<span class="col-12">
|
||||||
<div class="status-chip"
|
{{'TENANT-LISTING.FIELDS.CODE' | translate}}:
|
||||||
[ngClass]="{'status-chip-finalized': item.status === descriptionTemplateTypeStatuses.Finalized, 'status-chip-draft' : item.status === descriptionTemplateTypeStatuses.Draft}">
|
<small>
|
||||||
{{enumUtils.toDescriptionTemplateTypeStatusString(item.status) | nullifyValue}}
|
{{item?.code | nullifyValue}}
|
||||||
</div>
|
</small>
|
||||||
</div>
|
</span>
|
||||||
|
<br>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="isColumnSelected('createdAt')">
|
<ng-container *ngIf="isColumnSelected('createdAt')">
|
||||||
|
|
|
@ -1421,6 +1421,7 @@
|
||||||
"TRACKING-PROCESS": "Tracking Process",
|
"TRACKING-PROCESS": "Tracking Process",
|
||||||
"RETRY-COUNT": "Retry Count",
|
"RETRY-COUNT": "Retry Count",
|
||||||
"NOTIFIED-AT": "Notified At",
|
"NOTIFIED-AT": "Notified At",
|
||||||
|
"USER": "User",
|
||||||
"UPDATED-AT": "Updated",
|
"UPDATED-AT": "Updated",
|
||||||
"CREATED-AT": "Created",
|
"CREATED-AT": "Created",
|
||||||
"IS-ACTIVE": "Is Active"
|
"IS-ACTIVE": "Is Active"
|
||||||
|
@ -1433,6 +1434,7 @@
|
||||||
"CONTACT-TYPE": "Contact Type",
|
"CONTACT-TYPE": "Contact Type",
|
||||||
"TRACKING-STATE": "Tracking State",
|
"TRACKING-STATE": "Tracking State",
|
||||||
"TRACKING-PROCESS": "Tracking Process",
|
"TRACKING-PROCESS": "Tracking Process",
|
||||||
|
"USERS": "Users",
|
||||||
"CANCEL": "Cancel",
|
"CANCEL": "Cancel",
|
||||||
"APPLY-FILTERS": "Apply filters"
|
"APPLY-FILTERS": "Apply filters"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue