Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Sofia Papacharalampous 2024-05-23 15:17:51 +03:00
commit b36622334a
24 changed files with 258 additions and 160 deletions

View File

@ -10,6 +10,11 @@ public class AuthorizationProperties {
private String globalAdminRole; private String globalAdminRole;
private String tenantAdminRole; private String tenantAdminRole;
private String globalUserRole;
private String tenantUserRole;
private Boolean autoAssignGlobalAdminToNewTenants;
private List<String> allowedTenantRoles;
private List<String> allowedGlobalRoles;
public String getGlobalAdminRole() { public String getGlobalAdminRole() {
return this.globalAdminRole; return this.globalAdminRole;
@ -18,35 +23,6 @@ public class AuthorizationProperties {
public void setGlobalAdminRole(String globalAdminRole) { public void setGlobalAdminRole(String globalAdminRole) {
this.globalAdminRole = globalAdminRole; this.globalAdminRole = globalAdminRole;
} }
private Boolean autoAssignGlobalAdminToNewTenants;
public Boolean getAutoAssignGlobalAdminToNewTenants() {
return this.autoAssignGlobalAdminToNewTenants;
}
public void setAutoAssignGlobalAdminToNewTenants(Boolean autoAssignGlobalAdminToNewTenants) {
this.autoAssignGlobalAdminToNewTenants = autoAssignGlobalAdminToNewTenants;
}
private List<String> allowedTenantRoles;
public List<String> getAllowedTenantRoles() {
return this.allowedTenantRoles;
}
public void setAllowedTenantRoles(List<String> allowedTenantRoles) {
this.allowedTenantRoles = allowedTenantRoles;
}
private List<String> allowedGlobalRoles;
public List<String> getAllowedGlobalRoles() {
return this.allowedGlobalRoles;
}
public void setAllowedGlobalRoles(List<String> allowedGlobalRoles) {
this.allowedGlobalRoles = allowedGlobalRoles;
}
public String getTenantAdminRole() { public String getTenantAdminRole() {
return this.tenantAdminRole; return this.tenantAdminRole;
@ -55,4 +31,44 @@ public class AuthorizationProperties {
public void setTenantAdminRole(String tenantAdminRole) { public void setTenantAdminRole(String tenantAdminRole) {
this.tenantAdminRole = tenantAdminRole; this.tenantAdminRole = tenantAdminRole;
} }
public String getGlobalUserRole() {
return this.globalUserRole;
}
public void setGlobalUserRole(String globalUserRole) {
this.globalUserRole = globalUserRole;
}
public String getTenantUserRole() {
return this.tenantUserRole;
}
public void setTenantUserRole(String tenantUserRole) {
this.tenantUserRole = tenantUserRole;
}
public Boolean getAutoAssignGlobalAdminToNewTenants() {
return this.autoAssignGlobalAdminToNewTenants;
}
public void setAutoAssignGlobalAdminToNewTenants(Boolean autoAssignGlobalAdminToNewTenants) {
this.autoAssignGlobalAdminToNewTenants = autoAssignGlobalAdminToNewTenants;
}
public List<String> getAllowedTenantRoles() {
return this.allowedTenantRoles;
}
public void setAllowedTenantRoles(List<String> allowedTenantRoles) {
this.allowedTenantRoles = allowedTenantRoles;
}
public List<String> getAllowedGlobalRoles() {
return this.allowedGlobalRoles;
}
public void setAllowedGlobalRoles(List<String> allowedGlobalRoles) {
this.allowedGlobalRoles = allowedGlobalRoles;
}
} }

View File

@ -15,6 +15,6 @@ public class LocaleConfiguration {
} }
public LocaleProperties getProperties() { public LocaleProperties getProperties() {
return properties; return this.properties;
} }
} }

View File

@ -8,15 +8,15 @@ public class MultitenancyProperties {
private String defaultTenantCode; private String defaultTenantCode;
public boolean isMultitenant() { public boolean isMultitenant() {
return isMultitenant; return this.isMultitenant;
} }
public void setIsMultitenant(boolean multitenant) { public void setIsMultitenant(boolean multitenant) {
isMultitenant = multitenant; this.isMultitenant = multitenant;
} }
public String getDefaultTenantCode() { public String getDefaultTenantCode() {
return defaultTenantCode; return this.defaultTenantCode;
} }
public void setDefaultTenantCode(String defaultTenantCode) { public void setDefaultTenantCode(String defaultTenantCode) {

View File

@ -1,14 +1,13 @@
package org.opencdmp.commons.scope.tenant; package org.opencdmp.commons.scope.tenant;
import org.opencdmp.data.tenant.TenantScopedBaseEntity;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import org.hibernate.Session; import org.hibernate.Session;
import org.opencdmp.data.tenant.TenantScopedBaseEntity;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
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 javax.management.InvalidApplicationException;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -28,11 +27,11 @@ public class TenantScope {
} }
public Boolean isMultitenant() { public Boolean isMultitenant() {
return multitenancy.isMultitenant(); return this.multitenancy.isMultitenant();
} }
public String getDefaultTenantCode() { public String getDefaultTenantCode() {
return multitenancy.getDefaultTenantCode(); return this.multitenancy.getDefaultTenantCode();
} }
public Boolean isSet() { public Boolean isSet() {

View File

@ -1,12 +1,13 @@
package org.opencdmp.model.deleter; package org.opencdmp.model.deleter;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.UserCredentialEntity;
import org.opencdmp.query.UserCredentialQuery;
import gr.cite.tools.data.deleter.Deleter; import gr.cite.tools.data.deleter.Deleter;
import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService; import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.UserCredentialEntity;
import org.opencdmp.query.UserCredentialQuery;
import org.opencdmp.service.keycloak.KeycloakService;
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.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -19,22 +20,24 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@Component @Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class UserCredentialDeleter implements Deleter { public class UserCredentialDeleter implements Deleter {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserCredentialDeleter.class)); private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserCredentialDeleter.class));
private final TenantEntityManager entityManager; private final TenantEntityManager entityManager;
protected final QueryFactory queryFactory; protected final QueryFactory queryFactory;
private final KeycloakService keycloakService;
@Autowired @Autowired
public UserCredentialDeleter( public UserCredentialDeleter(
TenantEntityManager entityManager, TenantEntityManager entityManager,
QueryFactory queryFactory QueryFactory queryFactory, KeycloakService keycloakService
) { ) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.keycloakService = keycloakService;
} }
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException { public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
@ -62,6 +65,8 @@ public class UserCredentialDeleter implements Deleter {
logger.trace("deleting item"); logger.trace("deleting item");
this.entityManager.remove(item); this.entityManager.remove(item);
logger.trace("deleted item"); logger.trace("deleted item");
this.keycloakService.removeFromAllGroups(item.getExternalId());
} }
} }

View File

@ -1,7 +1,7 @@
package org.opencdmp.model.persist.actionconfirmation; package org.opencdmp.model.persist.actionconfirmation;
import org.opencdmp.commons.validation.BaseValidator;
import gr.cite.tools.validation.specification.Specification; import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.errorcode.ErrorThesaurusProperties; import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -20,7 +20,7 @@ public class RemoveCredentialRequestPersist {
public static final String _credentialId = "credentialId"; public static final String _credentialId = "credentialId";
public UUID getCredentialId() { public UUID getCredentialId() {
return credentialId; return this.credentialId;
} }
public void setCredentialId(UUID credentialId) { public void setCredentialId(UUID credentialId) {
@ -51,7 +51,7 @@ public class RemoveCredentialRequestPersist {
return Arrays.asList( return Arrays.asList(
this.spec() this.spec()
.must(() -> this.isValidGuid(item.getCredentialId())) .must(() -> this.isValidGuid(item.getCredentialId()))
.failOn(RemoveCredentialRequestPersist._credentialId).failWith(messageSource.getMessage("Validation_Required", new Object[]{RemoveCredentialRequestPersist._credentialId}, LocaleContextHolder.getLocale())) .failOn(RemoveCredentialRequestPersist._credentialId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{RemoveCredentialRequestPersist._credentialId}, LocaleContextHolder.getLocale()))
); );
} }
} }

View File

@ -1,10 +1,8 @@
package org.opencdmp.service.keycloak; package org.opencdmp.service.keycloak;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.keycloak.representations.idm.GroupRepresentation;
import java.util.HashMap; import java.util.List;
import java.util.UUID;
public interface KeycloakService { public interface KeycloakService {
@ -12,6 +10,10 @@ public interface KeycloakService {
void removeUserFromGroup(@NotNull String subjectId, String groupId); void removeUserFromGroup(@NotNull String subjectId, String groupId);
List<String> getUserGroups(String subjectId);
void removeFromAllGroups(String subjectId);
void addUserToGlobalRoleGroup(String subjectId, String role); void addUserToGlobalRoleGroup(String subjectId, String role);
void removeUserGlobalRoleGroup(@NotNull String subjectId, String role); void removeUserGlobalRoleGroup(@NotNull String subjectId, String role);

View File

@ -6,6 +6,7 @@ import org.opencdmp.convention.ConventionService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -33,7 +34,23 @@ public class KeycloakServiceImpl implements KeycloakService {
public void removeUserFromGroup(@NotNull String subjectId, String groupId) { public void removeUserFromGroup(@NotNull String subjectId, String groupId) {
this.api.users().removeUserFromGroup(subjectId, groupId); this.api.users().removeUserFromGroup(subjectId, groupId);
} }
@Override
public List<String> getUserGroups(String subjectId) {
if (this.configuration.getProperties().getAuthorities() == null) return new ArrayList<>();
List<GroupRepresentation> group = this.api.users().getGroups(subjectId);
if (group != null) return group.stream().map(GroupRepresentation::getId).toList();
return new ArrayList<>();
}
@Override
public void removeFromAllGroups(String subjectId){
List<String> existingGroups = this.getUserGroups(subjectId);
for (String existingGroup : existingGroups){
this.removeUserFromGroup(subjectId, existingGroup);
}
}
@Override @Override
public void addUserToGlobalRoleGroup(String subjectId, String role) { public void addUserToGlobalRoleGroup(String subjectId, String role) {
if (this.configuration.getProperties().getAuthorities() == null) return; if (this.configuration.getProperties().getAuthorities() == null) return;

View File

@ -1,17 +1,17 @@
package org.opencdmp.service.user; package org.opencdmp.service.user;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import org.opencdmp.model.user.User;
import org.opencdmp.model.persist.actionconfirmation.RemoveCredentialRequestPersist;
import org.opencdmp.model.persist.UserMergeRequestPersist;
import org.opencdmp.model.persist.UserPersist;
import org.opencdmp.model.persist.UserRolePatchPersist;
import gr.cite.tools.exception.MyApplicationException; import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException; import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException; import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException; import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.FieldSet; import gr.cite.tools.fieldset.FieldSet;
import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.JAXBException;
import org.opencdmp.model.persist.UserMergeRequestPersist;
import org.opencdmp.model.persist.UserPersist;
import org.opencdmp.model.persist.UserRolePatchPersist;
import org.opencdmp.model.persist.actionconfirmation.RemoveCredentialRequestPersist;
import org.opencdmp.model.user.User;
import javax.management.InvalidApplicationException; import javax.management.InvalidApplicationException;
import java.io.IOException; import java.io.IOException;
@ -40,5 +40,4 @@ public interface UserService {
void confirmMergeAccount(String token) throws InvalidApplicationException, IOException; void confirmMergeAccount(String token) throws InvalidApplicationException, IOException;
void confirmRemoveCredential(String token) throws InvalidApplicationException; void confirmRemoveCredential(String token) throws InvalidApplicationException;
} }

View File

@ -39,6 +39,7 @@ import org.opencdmp.commons.types.user.AdditionalInfoEntity;
import org.opencdmp.commons.types.usercredential.UserCredentialDataEntity; import org.opencdmp.commons.types.usercredential.UserCredentialDataEntity;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.*; import org.opencdmp.data.*;
import org.opencdmp.data.tenant.TenantScopedBaseEntity;
import org.opencdmp.errorcode.ErrorThesaurusProperties; import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.event.EventBroker; import org.opencdmp.event.EventBroker;
import org.opencdmp.event.UserTouchedEvent; import org.opencdmp.event.UserTouchedEvent;
@ -74,6 +75,7 @@ import java.io.PrintWriter;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -100,14 +102,11 @@ public class UserServiceImpl implements UserService {
private final XmlHandlingService xmlHandlingService; private final XmlHandlingService xmlHandlingService;
private final QueryFactory queryFactory; private final QueryFactory queryFactory;
private final UserScope userScope; private final UserScope userScope;
private final KeycloakService keycloakService; private final KeycloakService keycloakService;
private final ActionConfirmationService actionConfirmationService; private final ActionConfirmationService actionConfirmationService;
private final NotificationProperties notificationProperties; private final NotificationProperties notificationProperties;
private final NotifyIntegrationEventHandler eventHandler; private final NotifyIntegrationEventHandler eventHandler;
private final ValidatorFactory validatorFactory; private final ValidatorFactory validatorFactory;
private final ElasticService elasticService; private final ElasticService elasticService;
private final UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler; private final UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler;
private final UserRemovalIntegrationEventHandler userRemovalIntegrationEventHandler; private final UserRemovalIntegrationEventHandler userRemovalIntegrationEventHandler;
@ -193,7 +192,7 @@ public class UserServiceImpl implements UserService {
if (persist == null) return data; if (persist == null) return data;
if (persist.getOrganization() != null) { if (persist.getOrganization() != null) {
ReferenceEntity organization = this.buildReferenceEntity(persist.getOrganization()); ReferenceEntity organization = this.buildReferenceEntity(persist.getOrganization());
data.setOrganizationId(organization != null ? organization.getId() : null); data.setOrganizationId(organization.getId());
} }
data.setRoleOrganization(persist.getRoleOrganization()); data.setRoleOrganization(persist.getRoleOrganization());
data.setCulture(persist.getCulture()); data.setCulture(persist.getCulture());
@ -205,7 +204,7 @@ public class UserServiceImpl implements UserService {
private @NotNull ReferenceEntity buildReferenceEntity(ReferencePersist model) throws InvalidApplicationException { private @NotNull ReferenceEntity buildReferenceEntity(ReferencePersist model) throws InvalidApplicationException {
ReferenceEntity referenceEntity = null; ReferenceEntity referenceEntity;
if (this.conventionService.isValidGuid(model.getId())) { if (this.conventionService.isValidGuid(model.getId())) {
referenceEntity = this.entityManager.find(ReferenceEntity.class, model.getId()); referenceEntity = this.entityManager.find(ReferenceEntity.class, model.getId());
if (referenceEntity == null) if (referenceEntity == null)
@ -333,6 +332,8 @@ public class UserServiceImpl implements UserService {
this.eventBroker.emit(new UserTouchedEvent(data.getId())); this.eventBroker.emit(new UserTouchedEvent(data.getId()));
this.syncKeycloakRoles(data.getId());
this.userTouchedIntegrationEventHandler.handle(data.getId()); this.userTouchedIntegrationEventHandler.handle(data.getId());
return this.builderFactory.builder(UserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, User._id), data); return this.builderFactory.builder(UserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, User._id), data);
} }
@ -352,7 +353,6 @@ public class UserServiceImpl implements UserService {
item.setRole(roleName); item.setRole(roleName);
item.setCreatedAt(Instant.now()); item.setCreatedAt(Instant.now());
this.entityManager.persist(item); this.entityManager.persist(item);
this.keycloakService.addUserToGlobalRoleGroup(subjectId, roleName);
} }
foundIds.add(item.getId()); foundIds.add(item.getId());
} }
@ -360,7 +360,6 @@ public class UserServiceImpl implements UserService {
this.entityManager.flush(); this.entityManager.flush();
List<UserRoleEntity> toDelete = existingItems.stream().filter(x -> foundIds.stream().noneMatch(y -> y.equals(x.getId()))).collect(Collectors.toList()); List<UserRoleEntity> toDelete = existingItems.stream().filter(x -> foundIds.stream().noneMatch(y -> y.equals(x.getId()))).collect(Collectors.toList());
toDelete.forEach(x -> this.keycloakService.removeUserGlobalRoleGroup(subjectId, x.getRole()));
this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete); this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete);
this.entityManager.flush(); this.entityManager.flush();
@ -388,7 +387,6 @@ public class UserServiceImpl implements UserService {
item.setCreatedAt(Instant.now()); item.setCreatedAt(Instant.now());
item.setTenantId(this.tenantScope.getTenant()); item.setTenantId(this.tenantScope.getTenant());
this.entityManager.persist(item); this.entityManager.persist(item);
this.keycloakService.addUserToTenantRoleGroup(subjectId, this.tenantScope.getTenantCode(), roleName);
} }
foundIds.add(item.getId()); foundIds.add(item.getId());
} }
@ -396,13 +394,6 @@ public class UserServiceImpl implements UserService {
this.entityManager.flush(); this.entityManager.flush();
List<UserRoleEntity> toDelete = existingItems.stream().filter(x-> foundIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList()); List<UserRoleEntity> toDelete = existingItems.stream().filter(x-> foundIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList());
toDelete.forEach(x -> {
try {
this.keycloakService.removeUserTenantRoleGroup(subjectId, this.tenantScope.getTenantCode(), x.getRole());
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
});
this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete); this.deleterFactory.deleter(UserRoleDeleter.class).deleteAndSave(toDelete);
this.entityManager.flush(); this.entityManager.flush();
@ -506,7 +497,6 @@ public class UserServiceImpl implements UserService {
if (this.userScope.getUserIdSafe() == null) throw new MyForbiddenException(this.errors.getForbidden().getCode(), this.errors.getForbidden().getMessage()); if (this.userScope.getUserIdSafe() == null) throw new MyForbiddenException(this.errors.getForbidden().getCode(), this.errors.getForbidden().getMessage());
String token = this.createMergeAccountConfirmation(model.getEmail()); String token = this.createMergeAccountConfirmation(model.getEmail());
this.createMergeNotificationEvent(token, user, model.getEmail(), NotificationContactType.EMAIL); this.createMergeNotificationEvent(token, user, model.getEmail(), NotificationContactType.EMAIL);
} }
@ -571,8 +561,6 @@ public class UserServiceImpl implements UserService {
return persist.getToken(); return persist.getToken();
} }
private String createRemoveConfirmation(UUID credentialId) throws JAXBException, InvalidApplicationException { private String createRemoveConfirmation(UUID credentialId) throws JAXBException, InvalidApplicationException {
ActionConfirmationPersist persist = new ActionConfirmationPersist(); ActionConfirmationPersist persist = new ActionConfirmationPersist();
persist.setType(ActionConfirmationType.RemoveCredential); persist.setType(ActionConfirmationType.RemoveCredential);
@ -602,7 +590,7 @@ public class UserServiceImpl implements UserService {
this.checkActionState(action); this.checkActionState(action);
MergeAccountConfirmationEntity mergeAccountConfirmationEntity = this.xmlHandlingService.fromXmlSafe(MergeAccountConfirmationEntity.class, action.getData()); MergeAccountConfirmationEntity mergeAccountConfirmationEntity = this.xmlHandlingService.fromXmlSafe(MergeAccountConfirmationEntity.class, action.getData());
if (mergeAccountConfirmationEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{mergeAccountConfirmationEntity, MergeAccountConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (mergeAccountConfirmationEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{action.getId(), MergeAccountConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
UserContactInfoEntity userContactInfoEntity = this.queryFactory.query(UserContactInfoQuery.class).values(mergeAccountConfirmationEntity.getEmail()).types(ContactInfoType.Email).first(); UserContactInfoEntity userContactInfoEntity = this.queryFactory.query(UserContactInfoQuery.class).values(mergeAccountConfirmationEntity.getEmail()).types(ContactInfoType.Email).first();
if (userContactInfoEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{mergeAccountConfirmationEntity.getEmail(), User.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (userContactInfoEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{mergeAccountConfirmationEntity.getEmail(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));
@ -627,6 +615,29 @@ public class UserServiceImpl implements UserService {
this.userTouchedIntegrationEventHandler.handle(newUser.getId()); this.userTouchedIntegrationEventHandler.handle(newUser.getId());
this.userRemovalIntegrationEventHandler.handle(userToBeMerge.getId()); this.userRemovalIntegrationEventHandler.handle(userToBeMerge.getId());
if (!newUser.getId().equals(userToBeMerge.getId())) {
this.syncKeycloakRoles(newUser.getId());
}
}
private void syncKeycloakRoles(UUID userId){
List<UserCredentialEntity> userCredentials = this.queryFactory.query(UserCredentialQuery.class).disableTracking().userIds(userId).collect();
List<UserRoleEntity> userRoles = this.queryFactory.query(UserRoleQuery.class).disableTracking().userIds(userId).collect();
List<TenantEntity> tenants = this.queryFactory.query(TenantQuery.class).disableTracking().ids(userRoles.stream().map(TenantScopedBaseEntity::getTenantId).filter(Objects::nonNull).toList()).collect();
for (UserCredentialEntity userCredential : userCredentials){
this.keycloakService.removeFromAllGroups(userCredential.getExternalId());
for (UserRoleEntity userRole : userRoles) {
if (this.authorizationProperties.getAllowedGlobalRoles().contains(userRole.getRole())){
this.keycloakService.addUserToGlobalRoleGroup(userCredential.getExternalId(), userRole.getRole());
} else if (this.authorizationProperties.getAllowedTenantRoles().contains(userRole.getRole())){
String tenantCode = userRole.getTenantId() == null ? this.tenantScope.getDefaultTenantCode() : tenants.stream().filter(x-> x.getId().equals(userRole.getTenantId())).map(TenantEntity::getCode).findFirst().orElse(null);
if (!this.conventionService.isNullOrEmpty(tenantCode)) this.keycloakService.addUserToTenantRoleGroup(userCredential.getExternalId(), tenantCode, userRole.getRole());
}
}
}
} }
private void mergeNewUserToOld(UserEntity newUser, UserEntity oldUser) throws IOException, InvalidApplicationException { private void mergeNewUserToOld(UserEntity newUser, UserEntity oldUser) throws IOException, InvalidApplicationException {
@ -731,8 +742,6 @@ public class UserServiceImpl implements UserService {
} }
} }
public void confirmRemoveCredential(String token) throws InvalidApplicationException { public void confirmRemoveCredential(String token) throws InvalidApplicationException {
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.RemoveCredential).isActive(IsActive.Active).first(); ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.RemoveCredential).isActive(IsActive.Active).first();
if (action == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{token, ActionConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (action == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{token, ActionConfirmationEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
@ -740,12 +749,12 @@ public class UserServiceImpl implements UserService {
this.checkActionState(action); this.checkActionState(action);
RemoveCredentialRequestEntity removeCredentialRequestEntity = this.xmlHandlingService.fromXmlSafe(RemoveCredentialRequestEntity.class, action.getData()); RemoveCredentialRequestEntity removeCredentialRequestEntity = this.xmlHandlingService.fromXmlSafe(RemoveCredentialRequestEntity.class, action.getData());
if (removeCredentialRequestEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{removeCredentialRequestEntity, RemoveCredentialRequestEntity.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (removeCredentialRequestEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{action.getId(), RemoveCredentialRequestEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
UserCredentialEntity userCredentialEntity = this.queryFactory.query(UserCredentialQuery.class).ids(removeCredentialRequestEntity.getCredentialId()).first(); UserCredentialEntity userCredentialEntity = this.queryFactory.query(UserCredentialQuery.class).ids(removeCredentialRequestEntity.getCredentialId()).first();
if (userCredentialEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{removeCredentialRequestEntity.getCredentialId(), UserCredential.class.getSimpleName()}, LocaleContextHolder.getLocale())); if (userCredentialEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{removeCredentialRequestEntity.getCredentialId(), UserCredential.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.userScope.getUserIdSafe().equals(userCredentialEntity.getId())) throw new MyForbiddenException("Only requested user can approve"); if (!this.userScope.getUserIdSafe().equals(userCredentialEntity.getUserId())) throw new MyForbiddenException("Only requested user can approve");
if (userCredentialEntity.getData() != null){ if (userCredentialEntity.getData() != null){
UserCredentialDataEntity userCredentialDataEntity = this.jsonHandlingService.fromJsonSafe(UserCredentialDataEntity.class, userCredentialEntity.getData()); UserCredentialDataEntity userCredentialDataEntity = this.jsonHandlingService.fromJsonSafe(UserCredentialDataEntity.class, userCredentialEntity.getData());
@ -763,8 +772,16 @@ public class UserServiceImpl implements UserService {
this.entityManager.flush(); this.entityManager.flush();
this.keycloakService.removeFromAllGroups(userCredentialEntity.getExternalId());
this.addToDefaultUserGroups(userCredentialEntity.getExternalId());
this.userTouchedIntegrationEventHandler.handle(userCredentialEntity.getUserId()); this.userTouchedIntegrationEventHandler.handle(userCredentialEntity.getUserId());
} }
private void addToDefaultUserGroups(String subjectId){
this.keycloakService.addUserToGlobalRoleGroup(subjectId, this.authorizationProperties.getGlobalUserRole());
this.keycloakService.addUserToTenantRoleGroup(subjectId, this.tenantScope.getDefaultTenantCode(), this.authorizationProperties.getTenantUserRole());
}
private void checkActionState(ActionConfirmationEntity action) throws MyApplicationException { private void checkActionState(ActionConfirmationEntity action) throws MyApplicationException {
if (action.getStatus().equals(ActionConfirmationStatus.Accepted)){ if (action.getStatus().equals(ActionConfirmationStatus.Accepted)){

View File

@ -1,6 +1,8 @@
authorization: authorization:
globalAdminRole: Admin globalAdminRole: Admin
tenantAdminRole: TenantAdmin tenantAdminRole: TenantAdmin
globalUserRole: User
tenantUserRole: TenantUser
autoAssignGlobalAdminToNewTenants: true autoAssignGlobalAdminToNewTenants: true
allowedTenantRoles: allowedTenantRoles:
- TenantAdmin - TenantAdmin

View File

@ -106,11 +106,11 @@ export class UserService {
.post<boolean>(url, item).pipe( .post<boolean>(url, item).pipe(
catchError((error: any) => throwError(error))); catchError((error: any) => throwError(error)));
} }
removeCredentialAccount(item: RemoveCredentialRequestPersist): Observable<boolean> { removeCredentialAccount(item: RemoveCredentialRequestPersist): Observable<boolean> {
const url = `${this.apiBase}/mine/remove-credential-request`; const url = `${this.apiBase}/mine/remove-credential-request`;
console.log(item); console.log(item);
console.log(url); console.log(url);
return this.http return this.http
.post<boolean>(url, item).pipe( .post<boolean>(url, item).pipe(
@ -125,6 +125,14 @@ export class UserService {
catchError((error: any) => throwError(error))); catchError((error: any) => throwError(error)));
} }
confirmRemoveCredentialAccount(token: Guid): Observable<boolean> {
const url = `${this.apiBase}/mine/confirm-remove-credential/token/${token}`;
return this.http
.get<boolean>(url).pipe(
catchError((error: any) => throwError(error)));
}
// //
// Autocomplete Commons // Autocomplete Commons
// //

View File

@ -1,11 +1,7 @@
import { Component, OnInit } from "@angular/core"; import { Component, OnInit } from "@angular/core";
import { UntypedFormControl } from '@angular/forms';
import { MatDialog } from "@angular/material/dialog";
import { ActivatedRoute, Router } from "@angular/router"; import { ActivatedRoute, Router } from "@angular/router";
import { AuthService } from "@app/core/services/auth/auth.service";
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { UserService } from "@app/core/services/user/user.service"; import { UserService } from "@app/core/services/user/user.service";
import { PopupNotificationDialogComponent } from "@app/library/notification/popup/popup-notification.component";
import { BaseComponent } from '@common/base/base.component'; import { BaseComponent } from '@common/base/base.component';
import { Guid } from "@common/types/guid"; import { Guid } from "@common/types/guid";
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
@ -17,20 +13,14 @@ import { takeUntil } from "rxjs/operators";
styleUrls: ['./merge-email-confirmation.component.scss'] styleUrls: ['./merge-email-confirmation.component.scss']
}) })
export class MergeEmailConfirmation extends BaseComponent implements OnInit { export class MergeEmailConfirmation extends BaseComponent implements OnInit {
private token: Guid;
public emailFormControl = new UntypedFormControl('');
public mailSent: boolean = false;
private token: Guid;
get showForm(): boolean { get showForm(): boolean {
return this.token != null; return this.token != null;
} }
constructor( constructor(
//TODO: refactor
// private emailConfirmationService: MergeEmailConfirmationService,
// private authService: AuthService,
private userService: UserService, private userService: UserService,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
@ -45,30 +35,12 @@ export class MergeEmailConfirmation extends BaseComponent implements OnInit {
const token = params['token'] const token = params['token']
if (token != null) { if (token != null) {
this.token = token; this.token = token;
// this.showForm = false;
//TODO: refactor
// this.emailConfirmationService.emailConfirmation(token)
// .pipe(takeUntil(this._destroyed))
// .subscribe(
// result => {
// const email = this.authService.getUserProfileEmail();
// if(!email || !result || (email == result))
// this.authService.clear();
// this.uiNotificationService.snackBarNotification(this.language.instant('USER-PROFILE.MERGING-SUCCESS'), SnackBarNotificationLevel.Success);
// this.onCallbackEmailConfirmationSuccess();
// },
// error => this.onCallbackError(error)
// )
} else {
// this.showForm = true;
} }
}); });
} }
onConfirm(): void { onConfirm(): void {
console.log('onConfirm');
if (this.showForm === false) return; if (this.showForm === false) return;
console.log('active');
this.userService.confirmMergeAccount(this.token) this.userService.confirmMergeAccount(this.token)
.subscribe(result => { .subscribe(result => {
@ -80,7 +52,10 @@ export class MergeEmailConfirmation extends BaseComponent implements OnInit {
} }
onCallbackEmailConfirmationSuccess() { onCallbackEmailConfirmationSuccess() {
this.router.navigate(['home']); this.router.navigate(['home'])
.then(() => {
window.location.reload();
});
} }
onCallbackError(error: any) { onCallbackError(error: any) {

View File

@ -1 +1,28 @@
<div class="unlink-account">
<div class="container-fluid">
<div class="row">
<div class="col unlink-account-title">{{'UNLINK-ACCOUNT.TITLE' | translate}}</div>
</div>
<div *ngIf="showForm" class="row unlink-account-content">
<div class="col">
<div class="row justify-content-center">
<div class="col-auto">
<span>
{{ 'UNLINK-ACCOUNT.MESSAGES.CONFIRMATION' | translate }}
</span>
<!-- <span>Duo ea clita doming eu stet. Nonummy voluptua accusam sit eos aliquyam sit kasd lorem ut feugait no et soluta invidunt ea sanctus. Ut erat molestie sit sit diam dolores lorem nonumy quis consetetur. Elitr sed euismod illum sit consetetur esse at eum elitr sit dolores ut facer. Autem in aliquyam magna eos dolore eos amet ut magna sadipscing sea eum. Justo elitr aliquip praesent est exerci dolore commodo accusam dolor hendrerit rebum feugiat aliquyam sadipscing sed. Dolores dolore autem in et dolor at adipiscing ullamcorper invidunt vel. Et takimata ea amet et at sit kasd erat magna sed.</span> -->
</div>
</div>
<div class="row justify-content-center">
<div class="col-auto mt-4">
<!-- -->
<button type="button" class="normal-btn" (click)="onConfirm()">{{ 'UNLINK-ACCOUNT.ACTIONS.CONFIRM' | translate }}</button>
</div>
</div>
</div>
</div>
<ng-template #loading>
</ng-template>
</div>
</div>

View File

@ -0,0 +1,19 @@
.unlink-account {
height: fit-content;
//margin-top: 80px;
min-height: 100vh;
background-color: #ffffff;
}
.unlink-account-title {
font-size: 1.25rem;
color: #212121;
padding-top: 4.1875rem;
padding-left: 3.75rem;
padding-bottom: 4.0625rem;
}
.unlink-account-content {
margin-left: 9rem;
margin-right: 11rem;
}

View File

@ -1,7 +1,9 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { UserService } from '@app/core/services/user/user.service';
import { BaseComponent } from '@common/base/base.component'; import { BaseComponent } from '@common/base/base.component';
import { Guid } from '@common/types/guid';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { takeUntil } from "rxjs/operators"; import { takeUntil } from "rxjs/operators";
@ -10,32 +12,45 @@ import { takeUntil } from "rxjs/operators";
templateUrl: './unlink-email-confirmation.component.html' templateUrl: './unlink-email-confirmation.component.html'
}) })
export class UnlinkEmailConfirmation extends BaseComponent implements OnInit { export class UnlinkEmailConfirmation extends BaseComponent implements OnInit {
private token: Guid;
constructor(
get showForm(): boolean {
return this.token != null;
}
constructor(
private userService: UserService,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
private language: TranslateService, private language: TranslateService,
private uiNotificationService: UiNotificationService private uiNotificationService: UiNotificationService,
) { super(); } ) { super(); }
ngOnInit(): void { ngOnInit() {
this.route.params this.route.params
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(params => { .subscribe(params => {
const token = params['token'] const token = params['token']
if (token != null) { if (token != null) {
//TODO refactor this.token = token;
// this.emailConfirmationService.emailConfirmation(token)
// .pipe(takeUntil(this._destroyed))
// .subscribe(
// result => this.onCallbackEmailConfirmationSuccess(),
// error => this.onCallbackError(error)
// )
} }
}); });
} }
onCallbackEmailConfirmationSuccess() { onConfirm(): void {
if (this.showForm === false) return;
this.userService.confirmRemoveCredentialAccount(this.token)
.subscribe(result => {
if (result) {
this.onCallbackConfirmationSuccess();
}
},
error => this.onCallbackError(error));
}
onCallbackConfirmationSuccess() {
this.router.navigate(['home']); this.router.navigate(['home']);
} }
@ -43,10 +58,8 @@ export class UnlinkEmailConfirmation extends BaseComponent implements OnInit {
if (error.status === 302) { if (error.status === 302) {
this.uiNotificationService.snackBarNotification(this.language.instant('EMAIL-CONFIRMATION.EMAIL-FOUND'), SnackBarNotificationLevel.Warning); this.uiNotificationService.snackBarNotification(this.language.instant('EMAIL-CONFIRMATION.EMAIL-FOUND'), SnackBarNotificationLevel.Warning);
this.router.navigate(['home']); this.router.navigate(['home']);
} } else {
else { this.uiNotificationService.snackBarNotification(this.language.instant('EMAIL-CONFIRMATION.EXPIRED-EMAIL'), SnackBarNotificationLevel.Error);
this.uiNotificationService.snackBarNotification(this.language.instant('EMAIL-CONFIRMATION.EXPIRED-EMAIL'), SnackBarNotificationLevel.Error);
this.router.navigate(['login']);
} }
} }

View File

@ -160,6 +160,7 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
nameof<User>(x => x.createdAt), nameof<User>(x => x.createdAt),
nameof<User>(x => x.updatedAt), nameof<User>(x => x.updatedAt),
nameof<User>(x => x.hash), nameof<User>(x => x.hash),
`${nameof<User>(x => x.credentials)}.${nameof<UserCredential>(x => x.id)}`,
`${nameof<User>(x => x.credentials)}.${nameof<UserCredential>(x => x.data.email)}`, `${nameof<User>(x => x.credentials)}.${nameof<UserCredential>(x => x.data.email)}`,
`${nameof<User>(x => x.credentials)}.${nameof<UserCredential>(x => x.data.externalProviderNames)}`, `${nameof<User>(x => x.credentials)}.${nameof<UserCredential>(x => x.data.externalProviderNames)}`,
] ]
@ -326,28 +327,15 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
.subscribe(confirm => { .subscribe(confirm => {
if (confirm) { if (confirm) {
this.userService.removeCredentialAccount({ credentialId: userCredential.user.id }).subscribe(result => { this.userService.removeCredentialAccount({ credentialId: userCredential.id }).subscribe(result => {
//TODO this.dialog.open(PopupNotificationDialogComponent, {
data: {
title: this.language.instant('USER-PROFILE.UNLINK-ACCOUNT.TITLE'),
message: this.language.instant('USER-PROFILE.UNLINK-ACCOUNT.MESSAGE', {'accountToBeUnlinked': userCredential.data?.email})
}, maxWidth: '30em'
});
}, },
error => this.onCallbackError(error)); error => this.onCallbackError(error));
//TODO: refactor
// const unlinkAccountModel: UnlinkAccountRequestModel = {
// userId: this.currentUserId,
// email: userCredential.email,
// provider: userCredential.provider
// };
// this.unlinkAccountEmailConfirmation.sendConfirmationEmail(unlinkAccountModel).pipe(takeUntil(this._destroyed)).subscribe(
// result => {
// this.dialog.open(PopupNotificationDialogComponent, {
// data: {
// title: this.language.instant('USER-PROFILE.UNLINK-ACCOUNT.TITLE'),
// message: this.language.instant('USER-PROFILE.UNLINK-ACCOUNT.MESSAGE', { 'accountToBeUnlinked': userCredential.email })
// }, maxWidth: '35em'
// });
// },
// error => { this.onCallbackError(error); }
// );
} }
}); });
} }

View File

@ -4,9 +4,6 @@ import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.mod
import { CommonFormsModule } from '@common/forms/common-forms.module'; import { CommonFormsModule } from '@common/forms/common-forms.module';
import { FormValidationErrorsDialogModule } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.module'; import { FormValidationErrorsDialogModule } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.module';
import { CommonUiModule } from '@common/ui/common-ui.module'; import { CommonUiModule } from '@common/ui/common-ui.module';
import { LoginComponent } from '../auth/login/login.component';
import { LoginModule } from '../auth/login/login.module';
import { AddAccountDialogComponent } from './add-account/add-account-dialog.component';
import { AddAccountDialogModule } from './add-account/add-account-dialog.module'; import { AddAccountDialogModule } from './add-account/add-account-dialog.module';
import { UserProfileComponent } from './user-profile.component'; import { UserProfileComponent } from './user-profile.component';
import { UserProfileRoutingModule } from './user-profile.routing'; import { UserProfileRoutingModule } from './user-profile.routing';

View File

@ -2152,5 +2152,14 @@
"ACTIONS": { "ACTIONS": {
"CONFIRM": "Confirm" "CONFIRM": "Confirm"
} }
},
"UNLINK-ACCOUNT": {
"TITLE": "Unlink Your Account",
"MESSAGES": {
"CONFIRMATION": "Are you sure that you want to unlink this account?"
},
"ACTIONS": {
"CONFIRM": "Confirm"
}
} }
} }

View File

@ -271,7 +271,7 @@
<table border="0" cellpadding="0" cellspacing="0"> <table border="0" cellpadding="0" cellspacing="0">
<tbody> <tbody>
<tr> <tr>
<td> <a href="{installation-url}/merge/confirmation/{confirmationToken}" target="_blank">Confirm Merge Request</a> </td> <td> <a href="{installation-url}/login/merge/confirmation/{confirmationToken}" target="_blank">Confirm Merge Request</a> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -9,6 +9,6 @@
<h2>User {userName} have sent you a merge Request.</h2> <h2>User {userName} have sent you a merge Request.</h2>
<p>Please confirm that you want to merge your {installation-url} account with that account. <p>Please confirm that you want to merge your {installation-url} account with that account.
<br/>The link will expire in {expiration_time}.</p> <br/>The link will expire in {expiration_time}.</p>
<a href="{installation-url}/merge/confirmation/{confirmationToken}" target="_blank">Confirm Merge Request</a> <a href="{installation-url}/login/merge/confirmation/{confirmationToken}" target="_blank">Confirm Merge Request</a>
</body> </body>
</html> </html>

View File

@ -271,7 +271,7 @@
<table border="0" cellpadding="0" cellspacing="0"> <table border="0" cellpadding="0" cellspacing="0">
<tbody> <tbody>
<tr> <tr>
<td> <a href="{installation-url}/unlink/confirmation/{confirmationToken}" target="_blank">Confirm Unlink Request</a> </td> <td> <a href="{installation-url}/login/unlink/confirmation/{confirmationToken}" target="_blank">Confirm Unlink Request</a> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -9,6 +9,6 @@
<h2>You have made a request to unlink your email account in ARGOS.</h2> <h2>You have made a request to unlink your email account in ARGOS.</h2>
<p>Please confirm that you want to unlink your {email} account. <p>Please confirm that you want to unlink your {email} account.
<br/>The link will expire in {expiration_time}.</p> <br/>The link will expire in {expiration_time}.</p>
<a href="{installation-url}/unlink/confirmation/{confirmationToken}" target="_blank">Confirm Unlink Request</a> <a href="{installation-url}/login/unlink/confirmation/{confirmationToken}" target="_blank">Confirm Unlink Request</a>
</body> </body>
</html> </html>

View File

@ -1,11 +1,15 @@
package gr.cite.notification.integrationevent.inbox.notify; package gr.cite.notification.integrationevent.inbox.notify;
import gr.cite.notification.common.StringUtils; import gr.cite.notification.common.StringUtils;
import gr.cite.notification.common.enums.ContactInfoType;
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.UserContactInfoEntity;
import gr.cite.notification.integrationevent.inbox.ConsistencyHandler; import gr.cite.notification.integrationevent.inbox.ConsistencyHandler;
import gr.cite.notification.model.User; import gr.cite.notification.model.User;
import gr.cite.notification.model.UserContactInfo;
import gr.cite.notification.model.builder.UserBuilder; import gr.cite.notification.model.builder.UserBuilder;
import gr.cite.notification.query.UserContactInfoQuery;
import gr.cite.notification.query.UserQuery; import gr.cite.notification.query.UserQuery;
import gr.cite.tools.data.builder.BuilderFactory; import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.data.query.QueryFactory;
@ -39,9 +43,10 @@ public class NotifyConsistencyHandler implements ConsistencyHandler<NotifyConsis
User user = this.builderFactory.builder(UserBuilder.class).build(fieldSet, query.firstAs(fieldSet)); User user = this.builderFactory.builder(UserBuilder.class).build(fieldSet, query.firstAs(fieldSet));
if (user == null) if (user == null)
return false; return false;
return consistencyPredicates.getContactTypeHint() == null || consistencyPredicates.getContactTypeHint() == NotificationContactType.IN_APP || !StringUtils.isNullOrEmpty(consistencyPredicates.getContactHint()); Long activeEmails = this.queryFactory.query(UserContactInfoQuery.class).ids(consistencyPredicates.getUserId()).isActive(IsActive.Active).type(ContactInfoType.Email).count();
return consistencyPredicates.getContactTypeHint() == null || consistencyPredicates.getContactTypeHint() == NotificationContactType.IN_APP || !StringUtils.isNullOrEmpty(consistencyPredicates.getContactHint()) || activeEmails != 0;
} else {
return !StringUtils.isNullOrEmpty(consistencyPredicates.getContactHint());
} }
return true;
} }
} }