UserNotificationPreference changes

This commit is contained in:
Efstratios Giannopoulos 2024-04-26 18:10:10 +03:00
parent b58dd531ff
commit b267f2f30c
15 changed files with 203 additions and 99 deletions

View File

@ -6,15 +6,16 @@ BEGIN
CREATE TABLE public."ntf_UserNotificationPreference" CREATE TABLE public."ntf_UserNotificationPreference"
( (
id uuid NOT NULL,
"user" uuid NOT NULL, "user" uuid NOT NULL,
"type" uuid NOT NULL, "type" uuid NOT NULL,
"channel" smallint NOT NULL, "channel" smallint NOT NULL,
"ordinal" numeric NOT NULL, "ordinal" numeric NOT NULL,
"tenant" uuid, "tenant" uuid NULL,
"created_at" timestamp without time zone NOT NULL, "created_at" timestamp without time zone NOT NULL,
"updated_at" timestamp without time zone NOT NULL, "updated_at" timestamp without time zone NOT NULL,
"is_active" smallint NOT NULL DEFAULT 1, "is_active" smallint NOT NULL DEFAULT 1,
CONSTRAINT "ntf_UserNotificationPreference_pkey" PRIMARY KEY ("user", "type", "channel"), CONSTRAINT "ntf_UserNotificationPreference_pkey" PRIMARY KEY (id),
CONSTRAINT "ntf_UserNotificationPreference_tenant_fkey" FOREIGN KEY ("tenant") CONSTRAINT "ntf_UserNotificationPreference_tenant_fkey" FOREIGN KEY ("tenant")
REFERENCES public."ntf_Tenant" (id) MATCH SIMPLE REFERENCES public."ntf_Tenant" (id) MATCH SIMPLE
ON UPDATE NO ACTION ON UPDATE NO ACTION

View File

@ -1,8 +1,9 @@
import { Guid } from '@common/types/guid'; import { Guid } from '@common/types/guid';
import { NotificationType } from '@notification-service/core/enum/notification-type.enum'; import { NotificationType } from '@notification-service/core/enum/notification-type.enum';
import { NotificationContactType } from '../enum/notification-contact-type'; import { NotificationContactType } from '../enum/notification-contact-type';
import { BaseEntity, BaseEntityPersist } from '@common/base/base-entity.model';
export interface UserNotificationPreference { export interface UserNotificationPreference extends BaseEntity {
userId?: Guid; userId?: Guid;
type: NotificationType; type: NotificationType;
channel: NotificationContactType; channel: NotificationContactType;
@ -10,7 +11,7 @@ export interface UserNotificationPreference {
createdAt?: Date; createdAt?: Date;
} }
export interface UserNotificationPreferencePersist { export interface UserNotificationPreferencePersist extends BaseEntityPersist {
userId?: Guid; userId?: Guid;
notificationPreferences: { [key: string]: NotificationContactType[] }; notificationPreferences: { [key: string]: NotificationContactType[] };
} }

View File

@ -4,6 +4,8 @@ import { NotificationType } from '@notification-service/core/enum/notification-t
import { NotificationContactType } from '../enum/notification-contact-type'; import { NotificationContactType } from '../enum/notification-contact-type';
export class UserNotificationPreferenceLookup extends Lookup implements UserNotificationPreferenceFilter { export class UserNotificationPreferenceLookup extends Lookup implements UserNotificationPreferenceFilter {
ids: Guid[];
excludedIds: Guid[];
userIds?: Guid[]; userIds?: Guid[];
type?: NotificationType[]; type?: NotificationType[];
channel?: NotificationContactType[]; channel?: NotificationContactType[];
@ -14,6 +16,8 @@ export class UserNotificationPreferenceLookup extends Lookup implements UserNoti
} }
export interface UserNotificationPreferenceFilter { export interface UserNotificationPreferenceFilter {
ids: Guid[];
excludedIds: Guid[];
userIds?: Guid[]; userIds?: Guid[];
type?: NotificationType[]; type?: NotificationType[];
channel?: NotificationContactType[]; channel?: NotificationContactType[];

View File

@ -10,6 +10,7 @@ import { NotificationServiceEnumUtils } from '@notification-service/core/formatt
import { InAppNotificationService } from './http/inapp-notification.service'; import { InAppNotificationService } from './http/inapp-notification.service';
import { NotificationService } from './http/notification-service'; import { NotificationService } from './http/notification-service';
import { NotificationTemplateService } from './http/notification-template.service'; import { NotificationTemplateService } from './http/notification-template.service';
import { TenantConfigurationService } from './http/tenant-configuration.service';
// //
// //
@ -38,6 +39,7 @@ export class CoreNotificationServiceModule {
NotificationService, NotificationService,
InAppNotificationService, InAppNotificationService,
NotificationTemplateService, NotificationTemplateService,
TenantConfigurationService,
UserNotificationPreferenceService UserNotificationPreferenceService
], ],
}; };

View File

@ -4,8 +4,11 @@ import gr.cite.notification.audit.AuditableAction;
import gr.cite.notification.authorization.AuthorizationFlags; import gr.cite.notification.authorization.AuthorizationFlags;
import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.common.enums.IsActive;
import gr.cite.notification.common.enums.TenantConfigurationType; import gr.cite.notification.common.enums.TenantConfigurationType;
import gr.cite.notification.common.scope.tenant.TenantScope;
import gr.cite.notification.common.types.tenantconfiguration.NotifierListTenantConfigurationEntity; import gr.cite.notification.common.types.tenantconfiguration.NotifierListTenantConfigurationEntity;
import gr.cite.notification.data.TenantEntity;
import gr.cite.notification.data.UserNotificationPreferenceEntity; import gr.cite.notification.data.UserNotificationPreferenceEntity;
import gr.cite.notification.event.TenantConfigurationTouchedEvent;
import gr.cite.notification.model.UserNotificationPreference; import gr.cite.notification.model.UserNotificationPreference;
import gr.cite.notification.model.builder.UserNotificationPreferenceBuilder; import gr.cite.notification.model.builder.UserNotificationPreferenceBuilder;
import gr.cite.notification.model.censorship.UserNotificationPreferenceCensor; import gr.cite.notification.model.censorship.UserNotificationPreferenceCensor;
@ -30,9 +33,12 @@ import gr.cite.tools.validation.ValidationFilterAnnotation;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import javax.management.InvalidApplicationException;
import java.util.*; import java.util.*;
@RestController @RestController
@ -46,20 +52,22 @@ public class UserNotificationPreferenceController {
private final CensorFactory censorFactory; private final CensorFactory censorFactory;
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final MessageSource messageSource; private final MessageSource messageSource;
private final TenantScope tenantScope;
@Autowired @Autowired
public UserNotificationPreferenceController(BuilderFactory builderFactory, public UserNotificationPreferenceController(BuilderFactory builderFactory,
AuditService auditService, AuditService auditService,
UserNotificationPreferenceService userNotificationPreferenceService, UserNotificationPreferenceService userNotificationPreferenceService,
CensorFactory censorFactory, CensorFactory censorFactory,
QueryFactory queryFactory, QueryFactory queryFactory,
MessageSource messageSource) { MessageSource messageSource, TenantScope tenantScope) {
this.builderFactory = builderFactory; this.builderFactory = builderFactory;
this.auditService = auditService; this.auditService = auditService;
this.userNotificationPreferenceService = userNotificationPreferenceService; this.userNotificationPreferenceService = userNotificationPreferenceService;
this.censorFactory = censorFactory; this.censorFactory = censorFactory;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.messageSource = messageSource; this.messageSource = messageSource;
this.tenantScope = tenantScope;
} }
@PostMapping("query") @PostMapping("query")
@ -80,7 +88,7 @@ public class UserNotificationPreferenceController {
@GetMapping("user/{userId}/current") @GetMapping("user/{userId}/current")
@Transactional @Transactional
public List<UserNotificationPreference> current(@PathVariable UUID userId, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException { public List<UserNotificationPreference> current(@PathVariable UUID userId, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException {
logger.debug(new MapLogEntry("retrieving" + UserNotificationPreference.class.getSimpleName()).And("userId", userId).And("fields", fieldSet)); logger.debug(new MapLogEntry("retrieving" + UserNotificationPreference.class.getSimpleName()).And("userId", userId).And("fields", fieldSet));
this.censorFactory.censor(UserNotificationPreferenceCensor.class).censor(fieldSet, userId); this.censorFactory.censor(UserNotificationPreferenceCensor.class).censor(fieldSet, userId);
@ -89,6 +97,13 @@ public class UserNotificationPreferenceController {
ordering.addAscending(UserNotificationPreference._ordinal); ordering.addAscending(UserNotificationPreference._ordinal);
UserNotificationPreferenceQuery query = this.queryFactory.query(UserNotificationPreferenceQuery.class).userId(userId).isActives(IsActive.Active); UserNotificationPreferenceQuery query = this.queryFactory.query(UserNotificationPreferenceQuery.class).userId(userId).isActives(IsActive.Active);
query.setOrder(ordering); query.setOrder(ordering);
if (this.tenantScope.isMultitenant() && this.tenantScope.isSet()) {
if (!this.tenantScope.isDefaultTenant()) {
query.tenantIsSet(true).tenantIds(this.tenantScope.getTenant());
} else {
query.tenantIsSet(false);
}
}
List<UserNotificationPreference> model = this.builderFactory.builder(UserNotificationPreferenceBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.collectAs(fieldSet)); List<UserNotificationPreference> model = this.builderFactory.builder(UserNotificationPreferenceBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.collectAs(fieldSet));
this.auditService.track(AuditableAction.User_Notification_Preference_Lookup, Map.ofEntries( this.auditService.track(AuditableAction.User_Notification_Preference_Lookup, Map.ofEntries(

View File

@ -2,7 +2,6 @@ package gr.cite.notification.data;
import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.common.enums.IsActive;
import gr.cite.notification.common.enums.NotificationContactType; import gr.cite.notification.common.enums.NotificationContactType;
import gr.cite.notification.data.composite.CompositeUserNotificationPreferenceId;
import gr.cite.notification.data.conventers.IsActiveConverter; import gr.cite.notification.data.conventers.IsActiveConverter;
import gr.cite.notification.data.conventers.NotificationContactTypeConverter; import gr.cite.notification.data.conventers.NotificationContactTypeConverter;
import gr.cite.notification.data.tenant.TenantScopedBaseEntity; import gr.cite.notification.data.tenant.TenantScopedBaseEntity;
@ -13,22 +12,23 @@ import java.util.UUID;
@Entity @Entity
@Table(name = "\"UserNotificationPreference\"") @Table(name = "\"UserNotificationPreference\"")
@IdClass(CompositeUserNotificationPreferenceId.class)
public class UserNotificationPreferenceEntity extends TenantScopedBaseEntity { public class UserNotificationPreferenceEntity extends TenantScopedBaseEntity {
@Id @Id
@Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false)
private UUID id;
public static final String _id = "id";
@Column(name = "user", columnDefinition = "uuid", nullable = false) @Column(name = "user", columnDefinition = "uuid", nullable = false)
private UUID userId; private UUID userId;
public static final String _userId = "userId"; public static final String _userId = "userId";
@Id
@Column(name = "type", columnDefinition = "uuid", nullable = false) @Column(name = "type", columnDefinition = "uuid", nullable = false)
private UUID type; private UUID type;
public static final String _type = "type"; public static final String _type = "type";
@Id
@Column(name = "channel", nullable = false) @Column(name = "channel", nullable = false)
@Convert(converter = NotificationContactTypeConverter.class) @Convert(converter = NotificationContactTypeConverter.class)
private NotificationContactType channel; private NotificationContactType channel;
@ -56,6 +56,14 @@ public class UserNotificationPreferenceEntity extends TenantScopedBaseEntity {
public static final String _isActive = "isActive"; public static final String _isActive = "isActive";
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public UUID getUserId() { public UUID getUserId() {
return userId; return userId;
} }

View File

@ -1,45 +0,0 @@
package gr.cite.notification.data.composite;
import gr.cite.notification.common.enums.NotificationContactType;
import java.io.Serializable;
import java.util.UUID;
public class CompositeUserNotificationPreferenceId implements Serializable {
private UUID userId;
private UUID type;
private NotificationContactType channel;
public CompositeUserNotificationPreferenceId() {
}
public CompositeUserNotificationPreferenceId(UUID userId, UUID type, NotificationContactType channel) {
this.userId = userId;
this.type = type;
this.channel = channel;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public UUID getType() {
return type;
}
public void setType(UUID type) {
this.type = type;
}
public NotificationContactType getChannel() {
return channel;
}
public void setChannel(NotificationContactType channel) {
this.channel = channel;
}
}

View File

@ -8,6 +8,10 @@ import java.util.UUID;
public class UserNotificationPreference { public class UserNotificationPreference {
private UUID id;
public static final String _id = "id";
private UUID userId; private UUID userId;
public static final String _userId = "userId"; public static final String _userId = "userId";
@ -40,6 +44,14 @@ public class UserNotificationPreference {
public static final String _isActive = "isActive"; public static final String _isActive = "isActive";
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public UUID getUserId() { public UUID getUserId() {
return userId; return userId;
} }

View File

@ -42,6 +42,7 @@ public class UserNotificationPreferenceBuilder extends BaseBuilder<UserNotificat
List<UserNotificationPreference> models = new ArrayList<>(); List<UserNotificationPreference> models = new ArrayList<>();
for(UserNotificationPreferenceEntity d : data){ for(UserNotificationPreferenceEntity d : data){
UserNotificationPreference m = new UserNotificationPreference(); UserNotificationPreference m = new UserNotificationPreference();
if(fields.hasField(this.asIndexer(UserNotificationPreference._id))) m.setId(d.getId());
if(fields.hasField(this.asIndexer(UserNotificationPreference._userId))) m.setUserId(d.getUserId()); if(fields.hasField(this.asIndexer(UserNotificationPreference._userId))) m.setUserId(d.getUserId());
if(fields.hasField(this.asIndexer(UserNotificationPreference._tenantId))) m.setTenantId(d.getTenantId()); if(fields.hasField(this.asIndexer(UserNotificationPreference._tenantId))) m.setTenantId(d.getTenantId());
if(fields.hasField(this.asIndexer(UserNotificationPreference._type))) m.setType(d.getType()); if(fields.hasField(this.asIndexer(UserNotificationPreference._type))) m.setType(d.getType());

View File

@ -2,6 +2,8 @@ package gr.cite.notification.query;
import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.common.enums.IsActive;
import gr.cite.notification.common.enums.NotificationContactType; import gr.cite.notification.common.enums.NotificationContactType;
import gr.cite.notification.data.TenantConfigurationEntity;
import gr.cite.notification.data.UserCredentialEntity;
import gr.cite.notification.data.UserNotificationPreferenceEntity; import gr.cite.notification.data.UserNotificationPreferenceEntity;
import gr.cite.notification.model.UserNotificationPreference; import gr.cite.notification.model.UserNotificationPreference;
import gr.cite.tools.data.query.FieldResolver; import gr.cite.tools.data.query.FieldResolver;
@ -15,15 +17,16 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@Component @Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE) @Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class UserNotificationPreferenceQuery extends QueryBase<UserNotificationPreferenceEntity> { public class UserNotificationPreferenceQuery extends QueryBase<UserNotificationPreferenceEntity> {
private Collection<UUID> ids;
private Collection<UUID> excludedIds;
private List<UUID> userId; private List<UUID> userId;
private List<IsActive> isActives; private List<IsActive> isActives;
@ -32,6 +35,58 @@ public class UserNotificationPreferenceQuery extends QueryBase<UserNotificationP
private List<NotificationContactType> channel; private List<NotificationContactType> channel;
private Collection<UUID> tenantIds;
private Boolean tenantIsSet;
public UserNotificationPreferenceQuery ids(UUID value) {
this.ids = List.of(value);
return this;
}
public UserNotificationPreferenceQuery ids(UUID... value) {
this.ids = Arrays.asList(value);
return this;
}
public UserNotificationPreferenceQuery ids(Collection<UUID> values) {
this.ids = values;
return this;
}
public UserNotificationPreferenceQuery tenantIds(UUID value) {
this.tenantIds = List.of(value);
return this;
}
public UserNotificationPreferenceQuery tenantIds(UUID... value) {
this.tenantIds = Arrays.asList(value);
return this;
}
public UserNotificationPreferenceQuery tenantIds(Collection<UUID> values) {
this.tenantIds = values;
return this;
}
public UserNotificationPreferenceQuery tenantIsSet(Boolean values) {
this.tenantIsSet = values;
return this;
}
public UserNotificationPreferenceQuery excludedIds(Collection<UUID> values) {
this.excludedIds = values;
return this;
}
public UserNotificationPreferenceQuery excludedIds(UUID value) {
this.excludedIds = List.of(value);
return this;
}
public UserNotificationPreferenceQuery excludedIds(UUID... value) {
this.excludedIds = Arrays.asList(value);
return this;
}
public UserNotificationPreferenceQuery userId(UUID... userId) { public UserNotificationPreferenceQuery userId(UUID... userId) {
this.userId = List.of(userId); this.userId = List.of(userId);
return this; return this;
@ -74,7 +129,7 @@ public class UserNotificationPreferenceQuery extends QueryBase<UserNotificationP
@Override @Override
protected Boolean isFalseQuery() { protected Boolean isFalseQuery() {
return this.isNullOrEmpty(this.userId) && this.isNullOrEmpty(this.type) && this.isNullOrEmpty(this.channel); return this.isEmpty(this.ids) || this.isEmpty(this.tenantIds) ||this.isEmpty(this.excludedIds) ||this.isNullOrEmpty(this.userId) && this.isNullOrEmpty(this.type) && this.isNullOrEmpty(this.channel);
} }
@Override @Override
@ -85,6 +140,28 @@ public class UserNotificationPreferenceQuery extends QueryBase<UserNotificationP
@Override @Override
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) { protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
List<Predicate> predicates = new ArrayList<>(); List<Predicate> predicates = new ArrayList<>();
if (this.ids != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserNotificationPreferenceEntity._id));
for (UUID item : this.ids)
inClause.value(item);
predicates.add(inClause);
}
if (this.excludedIds != null) {
CriteriaBuilder.In<UUID> notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserNotificationPreferenceEntity._id));
for (UUID item : this.excludedIds)
notInClause.value(item);
predicates.add(notInClause.not());
}
if (this.tenantIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserNotificationPreferenceEntity._tenantId));
for (UUID item : this.tenantIds) inClause.value(item);
predicates.add(inClause);
}
if (this.tenantIsSet != null) {
if (this.tenantIsSet) predicates.add(queryContext.CriteriaBuilder.isNotNull(queryContext.Root.get(UserNotificationPreferenceEntity._tenantId)));
else predicates.add(queryContext.CriteriaBuilder.isNull(queryContext.Root.get(UserNotificationPreferenceEntity._tenantId)));
}
if (this.userId != null) { if (this.userId != null) {
predicates.add(queryContext.Root.get(UserNotificationPreferenceEntity._userId).in(this.userId)); predicates.add(queryContext.Root.get(UserNotificationPreferenceEntity._userId).in(this.userId));
} }
@ -119,6 +196,8 @@ public class UserNotificationPreferenceQuery extends QueryBase<UserNotificationP
protected String fieldNameOf(FieldResolver item) { protected String fieldNameOf(FieldResolver item) {
if (item.match(UserNotificationPreference._userId)) if (item.match(UserNotificationPreference._userId))
return UserNotificationPreferenceEntity._userId; return UserNotificationPreferenceEntity._userId;
else if (item.match(UserNotificationPreference._id))
return UserNotificationPreferenceEntity._id;
else if (item.match(UserNotificationPreference._tenantId)) else if (item.match(UserNotificationPreference._tenantId))
return UserNotificationPreferenceEntity._tenantId; return UserNotificationPreferenceEntity._tenantId;
else if (item.match(UserNotificationPreference._type)) else if (item.match(UserNotificationPreference._type))
@ -140,6 +219,7 @@ public class UserNotificationPreferenceQuery extends QueryBase<UserNotificationP
@Override @Override
protected UserNotificationPreferenceEntity convert(Tuple tuple, Set<String> columns) { protected UserNotificationPreferenceEntity convert(Tuple tuple, Set<String> columns) {
UserNotificationPreferenceEntity item = new UserNotificationPreferenceEntity(); UserNotificationPreferenceEntity item = new UserNotificationPreferenceEntity();
item.setId(QueryBase.convertSafe(tuple, columns, UserNotificationPreferenceEntity._id, UUID.class));
item.setUserId(QueryBase.convertSafe(tuple, columns, UserNotificationPreferenceEntity._userId, UUID.class)); item.setUserId(QueryBase.convertSafe(tuple, columns, UserNotificationPreferenceEntity._userId, UUID.class));
item.setChannel(QueryBase.convertSafe(tuple, columns, UserNotificationPreferenceEntity._channel, NotificationContactType.class)); item.setChannel(QueryBase.convertSafe(tuple, columns, UserNotificationPreferenceEntity._channel, NotificationContactType.class));
item.setType(QueryBase.convertSafe(tuple, columns, UserNotificationPreferenceEntity._type, UUID.class)); item.setType(QueryBase.convertSafe(tuple, columns, UserNotificationPreferenceEntity._type, UUID.class));

View File

@ -12,6 +12,8 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
public class UserNotificationPreferenceLookup extends Lookup { public class UserNotificationPreferenceLookup extends Lookup {
private List<UUID> ids;
private List<UUID> excludedIds;
private List<UUID> userId; private List<UUID> userId;
private List<UUID> type; private List<UUID> type;
private List<NotificationContactType> channel; private List<NotificationContactType> channel;
@ -45,6 +47,8 @@ public class UserNotificationPreferenceLookup extends Lookup {
if (this.userId != null) query.userId(this.userId); if (this.userId != null) query.userId(this.userId);
if (this.channel != null) query.channel(this.channel); if (this.channel != null) query.channel(this.channel);
if (this.type != null) query.type(this.type); if (this.type != null) query.type(this.type);
if (this.ids != null) query.ids(this.ids);
if (this.excludedIds != null) query.excludedIds(this.excludedIds);
this.enrichCommon(query); this.enrichCommon(query);

View File

@ -15,6 +15,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope; import org.springframework.web.context.annotation.RequestScope;
import javax.management.InvalidApplicationException;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -104,8 +105,13 @@ public class ChannelResolutionServiceImpl implements ChannelResolutionService{
private Map<UUID, List<NotificationContactType>> lookupOrCollectUserPolicies(List<UUID> users, UUID type) { private Map<UUID, List<NotificationContactType>> lookupOrCollectUserPolicies(List<UUID> users, UUID type) {
Map<UUID, List<NotificationContactType>> contactsByUser = new HashMap<>(); Map<UUID, List<NotificationContactType>> contactsByUser = new HashMap<>();
Map<UUID, List<UserNotificationPreference>> userNotificationPreferences = this.userNotificationPreferenceService.collectUserNotificationPreferences(users); Map<UUID, List<UserNotificationPreference>> userNotificationPreferences = null;
for (Map.Entry<UUID, List<UserNotificationPreference>> notificationPreference: userNotificationPreferences.entrySet()) try {
userNotificationPreferences = this.userNotificationPreferenceService.collectUserNotificationPreferences(users);
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
for (Map.Entry<UUID, List<UserNotificationPreference>> notificationPreference: userNotificationPreferences.entrySet())
{ {
contactsByUser.put(notificationPreference.getKey(), notificationPreference.getValue().stream().filter(x -> x.getType() != null && x.getType() == type && x.getChannel() != null).sorted(Comparator.comparingInt(x -> x.getOrdinal())).map(x -> x.getChannel()).collect(Collectors.toList())); contactsByUser.put(notificationPreference.getKey(), notificationPreference.getValue().stream().filter(x -> x.getType() != null && x.getType() == type && x.getChannel() != null).sorted(Comparator.comparingInt(x -> x.getOrdinal())).map(x -> x.getChannel()).collect(Collectors.toList()));
} }

View File

@ -73,17 +73,18 @@ public class NotificationServiceImpl implements NotificationService {
private final NotifierFactory notifierFactory; private final NotifierFactory notifierFactory;
private final ApplicationContext applicationContext; private final ApplicationContext applicationContext;
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final TenantScope tenantScope;
@Autowired @Autowired
public NotificationServiceImpl( public NotificationServiceImpl(
TenantEntityManager entityManager, TenantEntityManager entityManager,
AuthorizationService authService, AuthorizationService authService,
DeleterFactory deleterFactory, DeleterFactory deleterFactory,
BuilderFactory builderFactory, BuilderFactory builderFactory,
ConventionService conventionService, ConventionService conventionService,
ErrorThesaurusProperties errors, ErrorThesaurusProperties errors,
MessageSource messageSource, MessageSource messageSource,
ChannelResolutionService channelResolutionService, MessageBuilderFactory messageBuilderFactory, ContactExtractorFactory contactExtractorFactory, NotifierFactory notifierFactory, ApplicationContext applicationContext, QueryFactory queryFactory) { ChannelResolutionService channelResolutionService, MessageBuilderFactory messageBuilderFactory, ContactExtractorFactory contactExtractorFactory, NotifierFactory notifierFactory, ApplicationContext applicationContext, QueryFactory queryFactory, TenantScope tenantScope) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.authService = authService; this.authService = authService;
this.deleterFactory = deleterFactory; this.deleterFactory = deleterFactory;
@ -97,6 +98,7 @@ public class NotificationServiceImpl implements NotificationService {
this.notifierFactory = notifierFactory; this.notifierFactory = notifierFactory;
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.tenantScope = tenantScope;
} }
@Override @Override
@ -146,6 +148,7 @@ public class NotificationServiceImpl implements NotificationService {
public SendNotificationResult doNotify(NotificationEntity notification) { public SendNotificationResult doNotify(NotificationEntity notification) {
List<NotificationContactType> contactTypes = this.orderContactTypesFromPreferences(notification); List<NotificationContactType> contactTypes = this.orderContactTypesFromPreferences(notification);
if (this.conventionService.isListNullOrEmpty(contactTypes)) contactTypes = this.orderContactTypes(notification); if (this.conventionService.isListNullOrEmpty(contactTypes)) contactTypes = this.orderContactTypes(notification);
if (contactTypes == null) return null;
for (NotificationContactType contactType: contactTypes) { for (NotificationContactType contactType: contactTypes) {
SendNotificationResult result = this.sendNotification(notification, contactType); SendNotificationResult result = this.sendNotification(notification, contactType);
@ -160,8 +163,14 @@ public class NotificationServiceImpl implements NotificationService {
UserNotificationPreferenceQuery query = this.queryFactory.query(UserNotificationPreferenceQuery.class).userId(notification.getUserId()).type(notification.getType()).isActives(IsActive.Active); UserNotificationPreferenceQuery query = this.queryFactory.query(UserNotificationPreferenceQuery.class).userId(notification.getUserId()).type(notification.getType()).isActives(IsActive.Active);
query.setOrder(ordering); query.setOrder(ordering);
List<UserNotificationPreferenceEntity> preferences = query.collectAs(new BaseFieldSet().ensure(UserNotificationPreference._channel)); List<UserNotificationPreferenceEntity> preferences = query.collectAs(new BaseFieldSet().ensure(UserNotificationPreference._channel).ensure(UserNotificationPreference._tenantId).ensure(UserNotificationPreference._id));
if (!this.conventionService.isListNullOrEmpty(preferences)) return preferences.stream().map(x -> x.getChannel()).collect(Collectors.toList()); if (!this.conventionService.isListNullOrEmpty(preferences)) return preferences.stream().filter(x -> {
try {
return !this.tenantScope.isMultitenant() || this.tenantScope.isDefaultTenant() ? x.getTenantId() == null : x.getTenantId() == this.tenantScope.getTenant();
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
}).map(UserNotificationPreferenceEntity::getChannel).collect(Collectors.toList());
return null; return null;
} }

View File

@ -5,6 +5,7 @@ import gr.cite.notification.model.UserNotificationPreference;
import gr.cite.notification.model.persist.UserNotificationPreferencePersist; import gr.cite.notification.model.persist.UserNotificationPreferencePersist;
import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.fieldset.FieldSet;
import javax.management.InvalidApplicationException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -14,6 +15,6 @@ public interface UserNotificationPreferenceService {
List<UserNotificationPreference> persist(UserNotificationPreferencePersist model, FieldSet fieldSet); List<UserNotificationPreference> persist(UserNotificationPreferencePersist model, FieldSet fieldSet);
NotifierListTenantConfigurationEntity collectUserAvailableNotifierList(Set<UUID> notificationTypes); NotifierListTenantConfigurationEntity collectUserAvailableNotifierList(Set<UUID> notificationTypes);
List<UserNotificationPreference> collectUserNotificationPreferences(UUID id); List<UserNotificationPreference> collectUserNotificationPreferences(UUID id) throws InvalidApplicationException;
Map<UUID, List<UserNotificationPreference>> collectUserNotificationPreferences(List<UUID> ids); Map<UUID, List<UserNotificationPreference>> collectUserNotificationPreferences(List<UUID> ids) throws InvalidApplicationException;
} }

View File

@ -117,7 +117,7 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr
} }
@Override @Override
public List<UserNotificationPreference> collectUserNotificationPreferences(UUID id) { public List<UserNotificationPreference> collectUserNotificationPreferences(UUID id) throws InvalidApplicationException {
Map<UUID, List<UserNotificationPreference>> result = this.collectUserNotificationPreferences(List.of(id)); Map<UUID, List<UserNotificationPreference>> result = this.collectUserNotificationPreferences(List.of(id));
if (result != null) { if (result != null) {
return result.values().stream().flatMap(Collection::stream).collect(Collectors.toList()); return result.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
@ -127,18 +127,20 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr
} }
@Override @Override
public Map<UUID, List<UserNotificationPreference>> collectUserNotificationPreferences(List<UUID> ids) { public Map<UUID, List<UserNotificationPreference>> collectUserNotificationPreferences(List<UUID> ids) throws InvalidApplicationException {
UserNotificationPreferenceQuery query = this.queryFactory
.query(UserNotificationPreferenceQuery.class)
.userId(ids);
if (this.tenantScope.isMultitenant() && this.tenantScope.isSet()) {
if (!this.tenantScope.isDefaultTenant()) {
query.tenantIsSet(true).tenantIds(this.tenantScope.getTenant());
} else {
query.tenantIsSet(false);
}
}
return this.builderFactory.builder(UserNotificationPreferenceBuilder.class) return this.builderFactory.builder(UserNotificationPreferenceBuilder.class)
.build(new BaseFieldSet(UserNotificationPreference._userId, UserNotificationPreference._type, .build(new BaseFieldSet(UserNotificationPreference._userId, UserNotificationPreference._type,
UserNotificationPreference._channel, UserNotificationPreference._ordinal), this.queryFactory UserNotificationPreference._channel, UserNotificationPreference._ordinal, UserNotificationPreference._tenantId, UserNotificationPreference._id), query.collect()).stream()
.query(UserNotificationPreferenceQuery.class)
.userId(ids).collect()).stream().filter(x -> {
try {
return !this.tenantScope.isMultitenant() || this.tenantScope.isDefaultTenant() ? x.getTenantId() == null : x.getTenantId() == this.tenantScope.getTenant();
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.groupingBy(UserNotificationPreference::getUserId)); //GK: Yep that exist on JAVA Streams .collect(Collectors.groupingBy(UserNotificationPreference::getUserId)); //GK: Yep that exist on JAVA Streams
} }
@ -178,22 +180,24 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr
{ {
List<UserNotificationPreferenceEntity> preferences = null; List<UserNotificationPreferenceEntity> preferences = null;
try { try {
preferences = this.queryFactory UserNotificationPreferenceQuery query = this.queryFactory
.query(UserNotificationPreferenceQuery.class) .query(UserNotificationPreferenceQuery.class)
.type(type) .type(type)
.isActives(IsActive.Active) .isActives(IsActive.Active)
.userId(userId).collect(); .userId(userId);
if (this.tenantScope.isMultitenant() && this.tenantScope.isSet()) {
if (!this.tenantScope.isDefaultTenant()) {
query.tenantIsSet(true).tenantIds(this.tenantScope.getTenant());
} else {
query.tenantIsSet(false);
}
}
preferences = query.collect();
int ordinal = 0; int ordinal = 0;
List<UserNotificationPreferenceEntity> updatedPreferences = new ArrayList<>(); List<UserNotificationPreferenceEntity> updatedPreferences = new ArrayList<>();
for (NotificationContactType contactType : contactTypes) { for (NotificationContactType contactType : contactTypes) {
UserNotificationPreferenceEntity preference = preferences.stream().filter(x -> { UserNotificationPreferenceEntity preference = preferences.stream().filter(x -> x.getChannel() == contactType).findFirst().orElse(null);
try {
return x.getChannel() == contactType && (!this.tenantScope.isMultitenant() ||this.tenantScope.isDefaultTenant() ? x.getTenantId() == null : x.getTenantId() == this.tenantScope.getTenant());
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
}).findFirst().orElse(null);
boolean isUpdate = preference != null; boolean isUpdate = preference != null;
if (preference != null) { if (preference != null) {
@ -201,6 +205,7 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr
} else { } else {
preference = new UserNotificationPreferenceEntity(); preference = new UserNotificationPreferenceEntity();
preference.setId(UUID.randomUUID());
preference.setUserId(userId); preference.setUserId(userId);
preference.setType(type); preference.setType(type);
preference.setOrdinal(ordinal); preference.setOrdinal(ordinal);
@ -215,7 +220,7 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr
updatedPreferences.add(preference); updatedPreferences.add(preference);
ordinal++; ordinal++;
} }
List<UserNotificationPreferenceEntity> toDelete = preferences.stream().filter(x -> !updatedPreferences.stream().map(y-> y.getChannel()).collect(Collectors.toList()).contains(x.getChannel())).collect(Collectors.toList()); List<UserNotificationPreferenceEntity> toDelete = preferences.stream().filter(x -> !updatedPreferences.stream().map(UserNotificationPreferenceEntity::getChannel).toList().contains(x.getChannel())).toList();
for (UserNotificationPreferenceEntity deletable: toDelete) { for (UserNotificationPreferenceEntity deletable: toDelete) {
this.entityManager.remove(deletable); this.entityManager.remove(deletable);
} }