change idpclaims.yml and add user interceptor
This commit is contained in:
parent
1fb516c8ef
commit
28238c7a6d
|
@ -3,7 +3,7 @@ package gr.cite.notification.web;
|
||||||
import gr.cite.notification.web.scope.tenant.TenantInterceptor;
|
import gr.cite.notification.web.scope.tenant.TenantInterceptor;
|
||||||
import gr.cite.notification.web.scope.tenant.TenantScopeClaimInterceptor;
|
import gr.cite.notification.web.scope.tenant.TenantScopeClaimInterceptor;
|
||||||
import gr.cite.notification.web.scope.tenant.TenantScopeHeaderInterceptor;
|
import gr.cite.notification.web.scope.tenant.TenantScopeHeaderInterceptor;
|
||||||
import gr.cite.notification.web.scope.user.UserInterceptor;
|
import gr.cite.notification.web.interceptors.UserInterceptor;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class NotificationTemplateController {
|
||||||
public QueryResult<NotificationTemplate> query(@RequestBody NotificationTemplateLookup lookup) throws MyApplicationException, MyForbiddenException {
|
public QueryResult<NotificationTemplate> query(@RequestBody NotificationTemplateLookup lookup) throws MyApplicationException, MyForbiddenException {
|
||||||
logger.debug("querying {}", NotificationTemplate.class.getSimpleName());
|
logger.debug("querying {}", NotificationTemplate.class.getSimpleName());
|
||||||
|
|
||||||
//this.censorFactory.censor(NotificationTemplateCensor.class).censor(lookup.getProject()); TODO
|
this.censorFactory.censor(NotificationTemplateCensor.class).censor(lookup.getProject());
|
||||||
|
|
||||||
NotificationTemplateQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrPermission);
|
NotificationTemplateQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrPermission);
|
||||||
List<NotificationTemplateEntity> data = query.collectAs(lookup.getProject());
|
List<NotificationTemplateEntity> data = query.collectAs(lookup.getProject());
|
||||||
|
@ -80,7 +80,7 @@ public class NotificationTemplateController {
|
||||||
public NotificationTemplate get(@PathVariable UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
public NotificationTemplate get(@PathVariable UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
||||||
logger.debug(new MapLogEntry("retrieving" + NotificationTemplate.class.getSimpleName()).And("id", id).And("fields", fieldSet));
|
logger.debug(new MapLogEntry("retrieving" + NotificationTemplate.class.getSimpleName()).And("id", id).And("fields", fieldSet));
|
||||||
|
|
||||||
// this.censorFactory.censor(NotificationTemplateCensor.class).censor(fieldSet); TODO
|
this.censorFactory.censor(NotificationTemplateCensor.class).censor(fieldSet);
|
||||||
|
|
||||||
NotificationTemplateQuery query = this.queryFactory.query(NotificationTemplateQuery.class).authorize(AuthorizationFlags.OwnerOrPermission).ids(id);
|
NotificationTemplateQuery query = this.queryFactory.query(NotificationTemplateQuery.class).authorize(AuthorizationFlags.OwnerOrPermission).ids(id);
|
||||||
NotificationTemplate model = this.builderFactory.builder(NotificationTemplateBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.first());
|
NotificationTemplate model = this.builderFactory.builder(NotificationTemplateBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.first());
|
||||||
|
|
|
@ -0,0 +1,299 @@
|
||||||
|
package gr.cite.notification.web.interceptors;
|
||||||
|
|
||||||
|
|
||||||
|
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
||||||
|
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
|
||||||
|
import gr.cite.notification.common.JsonHandlingService;
|
||||||
|
import gr.cite.notification.common.enums.ContactInfoType;
|
||||||
|
import gr.cite.notification.common.enums.IsActive;
|
||||||
|
import gr.cite.notification.common.lock.LockByKeyManager;
|
||||||
|
import gr.cite.notification.common.scope.user.UserScope;
|
||||||
|
import gr.cite.notification.common.types.user.AdditionalInfoEntity;
|
||||||
|
import gr.cite.notification.data.UserContactInfoEntity;
|
||||||
|
import gr.cite.notification.data.UserCredentialEntity;
|
||||||
|
import gr.cite.notification.data.UserEntity;
|
||||||
|
import gr.cite.notification.data.UserRoleEntity;
|
||||||
|
import gr.cite.notification.model.UserContactInfo;
|
||||||
|
import gr.cite.notification.model.UserCredential;
|
||||||
|
import gr.cite.notification.model.UserRole;
|
||||||
|
import gr.cite.notification.query.UserContactInfoQuery;
|
||||||
|
import gr.cite.notification.query.UserCredentialQuery;
|
||||||
|
import gr.cite.notification.query.UserRoleQuery;
|
||||||
|
import gr.cite.tools.data.query.QueryFactory;
|
||||||
|
import gr.cite.tools.exception.MyForbiddenException;
|
||||||
|
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
import org.springframework.transaction.TransactionDefinition;
|
||||||
|
import org.springframework.transaction.TransactionStatus;
|
||||||
|
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.context.request.WebRequest;
|
||||||
|
import org.springframework.web.context.request.WebRequestInterceptor;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class UserInterceptor implements WebRequestInterceptor {
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserInterceptor.class));
|
||||||
|
private final UserScope userScope;
|
||||||
|
private final ClaimExtractor claimExtractor;
|
||||||
|
private final CurrentPrincipalResolver currentPrincipalResolver;
|
||||||
|
private final PlatformTransactionManager transactionManager;
|
||||||
|
private final UserInterceptorCacheService userInterceptorCacheService;
|
||||||
|
private final JsonHandlingService jsonHandlingService;
|
||||||
|
private final QueryFactory queryFactory;
|
||||||
|
private final LockByKeyManager lockByKeyManager;
|
||||||
|
@PersistenceContext
|
||||||
|
public EntityManager entityManager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public UserInterceptor(
|
||||||
|
UserScope userScope,
|
||||||
|
ClaimExtractor claimExtractor,
|
||||||
|
CurrentPrincipalResolver currentPrincipalResolver,
|
||||||
|
PlatformTransactionManager transactionManager,
|
||||||
|
UserInterceptorCacheService userInterceptorCacheService,
|
||||||
|
JsonHandlingService jsonHandlingService,
|
||||||
|
QueryFactory queryFactory,
|
||||||
|
LockByKeyManager lockByKeyManager) {
|
||||||
|
this.userScope = userScope;
|
||||||
|
this.currentPrincipalResolver = currentPrincipalResolver;
|
||||||
|
this.claimExtractor = claimExtractor;
|
||||||
|
this.transactionManager = transactionManager;
|
||||||
|
this.userInterceptorCacheService = userInterceptorCacheService;
|
||||||
|
this.jsonHandlingService = jsonHandlingService;
|
||||||
|
this.queryFactory = queryFactory;
|
||||||
|
this.lockByKeyManager = lockByKeyManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preHandle(WebRequest request) throws InterruptedException {
|
||||||
|
UUID userId = null;
|
||||||
|
if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) {
|
||||||
|
String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal());
|
||||||
|
if (subjectId == null || subjectId.isBlank()) throw new MyForbiddenException("Empty subjects not allowed");
|
||||||
|
|
||||||
|
UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId));
|
||||||
|
if (cacheValue != null && emailExistsToUser(cacheValue.getEmails()) && userRolesSynced(cacheValue.getRoles())) {
|
||||||
|
userId = cacheValue.getUserId();
|
||||||
|
} else {
|
||||||
|
boolean usedResource = false;
|
||||||
|
try {
|
||||||
|
usedResource = this.lockByKeyManager.tryLock(subjectId, 5000, TimeUnit.MILLISECONDS);
|
||||||
|
String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal());
|
||||||
|
|
||||||
|
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||||
|
definition.setName(UUID.randomUUID().toString());
|
||||||
|
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
|
||||||
|
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||||
|
TransactionStatus status = null;
|
||||||
|
try {
|
||||||
|
status = transactionManager.getTransaction(definition);
|
||||||
|
userId = this.findExistingUserFromDb(subjectId);
|
||||||
|
boolean isNewUser = userId == null;
|
||||||
|
if (isNewUser) {
|
||||||
|
UserEntity user = this.addNewUser(subjectId, email);
|
||||||
|
userId = user.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNewUser) this.syncUserWithClaims(userId);
|
||||||
|
|
||||||
|
this.entityManager.flush();
|
||||||
|
transactionManager.commit(status);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
if (status != null) transactionManager.rollback(status);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheValue = new UserInterceptorCacheService.UserInterceptorCacheValue(subjectId, userId);
|
||||||
|
cacheValue.setEmails(new ArrayList<>());
|
||||||
|
if (email != null && !email.isBlank()) cacheValue.getEmails().add(email);
|
||||||
|
cacheValue.setRoles(claimExtractor.roles(currentPrincipalResolver.currentPrincipal()));
|
||||||
|
|
||||||
|
this.userInterceptorCacheService.put(cacheValue);
|
||||||
|
} finally {
|
||||||
|
if (usedResource) this.lockByKeyManager.unlock(subjectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.userScope.setUserId(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncUserWithClaims(UUID userId){
|
||||||
|
List<String> existingUserEmails = this.collectUserEmails(userId);
|
||||||
|
List<String> existingUserRoles = this.collectUserRoles(userId);
|
||||||
|
if (!this.emailExistsToUser(existingUserEmails)){
|
||||||
|
String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal());
|
||||||
|
long contactUsedByOthersCount = this.queryFactory.query(UserContactInfoQuery.class).excludedUserIds(userId).type(ContactInfoType.Email).values(email).count();
|
||||||
|
if (contactUsedByOthersCount > 0) {
|
||||||
|
logger.warn("user contact exists to other user" + email);
|
||||||
|
} else {
|
||||||
|
Long emailContactsCount = this.queryFactory.query(UserContactInfoQuery.class).userIds(userId).type(ContactInfoType.Email).count();
|
||||||
|
UserContactInfoEntity contactInfo = this.buildEmailContact(userId, email);
|
||||||
|
contactInfo.setOrdinal(emailContactsCount.intValue());
|
||||||
|
this.entityManager.persist(contactInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.userRolesSynced(existingUserRoles)){
|
||||||
|
this.syncRoles(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private UUID findExistingUserFromDb(String subjectId){
|
||||||
|
UserCredentialEntity userCredential = this.queryFactory.query(UserCredentialQuery.class).externalIds(subjectId).firstAs(new BaseFieldSet().ensure(UserCredential._user));
|
||||||
|
if (userCredential != null) {
|
||||||
|
return userCredential.getUserId();
|
||||||
|
} else {
|
||||||
|
String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal());
|
||||||
|
if (email != null && !email.isBlank()) {
|
||||||
|
UserContactInfoEntity userContactInfo = this.queryFactory.query(UserContactInfoQuery.class).type(ContactInfoType.Email).values(email).firstAs(new BaseFieldSet().ensure(UserContactInfo._user));
|
||||||
|
if (userContactInfo != null) {
|
||||||
|
UserCredentialEntity credential = this.buildCredential(userContactInfo.getUserId(), subjectId);
|
||||||
|
this.entityManager.persist(credential);
|
||||||
|
|
||||||
|
return credential.getUserId();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new MyForbiddenException("Email is required");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncRoles(UUID userId){
|
||||||
|
List<String> claimsRoles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal());
|
||||||
|
if (claimsRoles == null) claimsRoles = new ArrayList<>();
|
||||||
|
claimsRoles = claimsRoles.stream().filter(x-> x != null && !x.isBlank()).distinct().collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<UserRoleEntity> existingUserRoles = this.queryFactory.query(UserRoleQuery.class).userIds(userId).collect();
|
||||||
|
List<UUID> foundRoles = new ArrayList<>();
|
||||||
|
for (String claimRole : claimsRoles) {
|
||||||
|
UserRoleEntity roleEntity = existingUserRoles.stream().filter(x-> x.getRole().equals(claimRole)).findFirst().orElse(null);
|
||||||
|
if (roleEntity == null) {
|
||||||
|
roleEntity = this.buildRole(userId, claimRole);
|
||||||
|
this.entityManager.persist(roleEntity);
|
||||||
|
}
|
||||||
|
foundRoles.add(roleEntity.getId());
|
||||||
|
}
|
||||||
|
for (UserRoleEntity existing: existingUserRoles) {
|
||||||
|
if (!foundRoles.contains(existing.getId())){
|
||||||
|
this.entityManager.remove(existing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> collectUserRoles(UUID userId){
|
||||||
|
List<UserRoleEntity> items = this.queryFactory.query(UserRoleQuery.class).userIds(userId).collectAs(new BaseFieldSet().ensure(UserRole._role));
|
||||||
|
return items == null ? new ArrayList<>() : items.stream().map(UserRoleEntity::getRole).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> collectUserEmails(UUID userId){
|
||||||
|
List<UserContactInfoEntity> items = this.queryFactory.query(UserContactInfoQuery.class).userIds(userId).type(ContactInfoType.Email).collectAs(new BaseFieldSet().ensure(UserContactInfo._value));
|
||||||
|
return items == null ? new ArrayList<>() : items.stream().map(UserContactInfoEntity::getValue).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean emailExistsToUser(List<String> existingUserEmails){
|
||||||
|
String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal());
|
||||||
|
return email == null || email.isBlank() ||
|
||||||
|
(existingUserEmails != null && existingUserEmails.stream().anyMatch(email::equals));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean userRolesSynced(List<String> existingUserRoles){
|
||||||
|
List<String> claimsRoles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal());
|
||||||
|
if (claimsRoles == null) claimsRoles = new ArrayList<>();
|
||||||
|
if (existingUserRoles == null) existingUserRoles = new ArrayList<>();
|
||||||
|
claimsRoles = claimsRoles.stream().filter(x-> x != null && !x.isBlank()).distinct().collect(Collectors.toList());
|
||||||
|
existingUserRoles = existingUserRoles.stream().filter(x-> x != null && !x.isBlank()).distinct().collect(Collectors.toList());
|
||||||
|
if (claimsRoles.size() != existingUserRoles.size()) return false;
|
||||||
|
|
||||||
|
for (String claim : claimsRoles ) {
|
||||||
|
if (existingUserRoles.stream().noneMatch(claim::equalsIgnoreCase)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserCredentialEntity buildCredential(UUID userId, String subjectId){
|
||||||
|
UserCredentialEntity data = new UserCredentialEntity();
|
||||||
|
data.setId(UUID.randomUUID());
|
||||||
|
data.setUserId(userId);
|
||||||
|
data.setCreatedAt(Instant.now());
|
||||||
|
data.setExternalId(subjectId);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserRoleEntity buildRole(UUID userId, String role){
|
||||||
|
UserRoleEntity data = new UserRoleEntity();
|
||||||
|
data.setId(UUID.randomUUID());
|
||||||
|
data.setUserId(userId);
|
||||||
|
data.setRole(role);
|
||||||
|
data.setCreatedAt(Instant.now());
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserContactInfoEntity buildEmailContact(UUID userId, String email){
|
||||||
|
UserContactInfoEntity data = new UserContactInfoEntity();
|
||||||
|
data.setId(UUID.randomUUID());
|
||||||
|
data.setUserId(userId);
|
||||||
|
data.setValue(email);
|
||||||
|
data.setType(ContactInfoType.Email);
|
||||||
|
data.setOrdinal(0);
|
||||||
|
data.setCreatedAt(Instant.now());
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private UserEntity addNewUser(String subjectId, String email){
|
||||||
|
List<String> roles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal());
|
||||||
|
String name = this.claimExtractor.name(this.currentPrincipalResolver.currentPrincipal());
|
||||||
|
|
||||||
|
UserEntity user = new UserEntity();
|
||||||
|
user.setId(UUID.randomUUID());
|
||||||
|
user.setName(name);
|
||||||
|
user.setCreatedAt(Instant.now());
|
||||||
|
user.setUpdatedAt(Instant.now());
|
||||||
|
user.setIsActive(IsActive.Active);
|
||||||
|
user.setAdditionalInfo(this.jsonHandlingService.toJsonSafe(new AdditionalInfoEntity()));
|
||||||
|
this.entityManager.persist(user);
|
||||||
|
|
||||||
|
UserCredentialEntity credential = this.buildCredential(user.getId(), subjectId);
|
||||||
|
this.entityManager.persist(credential);
|
||||||
|
|
||||||
|
if (email != null && !email.isBlank()) {
|
||||||
|
UserContactInfoEntity contactInfo = this.buildEmailContact(user.getId(), email);
|
||||||
|
this.entityManager.persist(contactInfo);
|
||||||
|
}
|
||||||
|
if (roles != null) {
|
||||||
|
for (String role: roles) {
|
||||||
|
UserRoleEntity roleEntity = this.buildRole(user.getId(), role);
|
||||||
|
this.entityManager.persist(roleEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postHandle(@NonNull WebRequest request, ModelMap model) {
|
||||||
|
this.userScope.setUserId(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterCompletion(@NonNull WebRequest request, Exception ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package gr.cite.notification.web.interceptors;
|
||||||
|
|
||||||
|
import gr.cite.tools.cache.CacheOptions;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "cache.user-by-subject-id")
|
||||||
|
public class UserInterceptorCacheOptions extends CacheOptions {
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package gr.cite.notification.web.interceptors;
|
||||||
|
|
||||||
|
import gr.cite.notification.convention.ConventionService;
|
||||||
|
import gr.cite.tools.cache.CacheService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> {
|
||||||
|
|
||||||
|
public static class UserInterceptorCacheValue {
|
||||||
|
|
||||||
|
public UserInterceptorCacheValue() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserInterceptorCacheValue(String subjectId, UUID userId) {
|
||||||
|
this.subjectId = subjectId;
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String subjectId;
|
||||||
|
|
||||||
|
public String getSubjectId() {
|
||||||
|
return subjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubjectId(String subjectId) {
|
||||||
|
this.subjectId = subjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UUID userId;
|
||||||
|
private List<String> roles;
|
||||||
|
private List<String> emails;
|
||||||
|
|
||||||
|
public UUID getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(UUID userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRoles() {
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoles(List<String> roles) {
|
||||||
|
this.roles = roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getEmails() {
|
||||||
|
return emails;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmails(List<String> emails) {
|
||||||
|
this.emails = emails;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) {
|
||||||
|
super(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<UserInterceptorCacheValue> valueClass() {
|
||||||
|
return UserInterceptorCacheValue.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String keyOf(UserInterceptorCacheValue value) {
|
||||||
|
return this.buildKey(value.getSubjectId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String buildKey(String subject) {
|
||||||
|
HashMap<String, String> keyParts = new HashMap<>();
|
||||||
|
keyParts.put("$subject$", subject);
|
||||||
|
return this.generateKey(keyParts);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,154 +1,154 @@
|
||||||
package gr.cite.notification.web.scope.user;
|
//package gr.cite.notification.web.scope.user;
|
||||||
|
//
|
||||||
|
//
|
||||||
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
//import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
||||||
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
|
//import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
|
||||||
import gr.cite.notification.common.enums.IsActive;
|
//import gr.cite.notification.common.enums.IsActive;
|
||||||
import gr.cite.notification.common.scope.user.UserScope;
|
//import gr.cite.notification.common.scope.user.UserScope;
|
||||||
import gr.cite.notification.data.UserEntity;
|
//import gr.cite.notification.data.UserEntity;
|
||||||
import gr.cite.notification.locale.LocaleService;
|
//import gr.cite.notification.locale.LocaleService;
|
||||||
import gr.cite.tools.logging.LoggerService;
|
//import gr.cite.tools.logging.LoggerService;
|
||||||
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.lang.NonNull;
|
//import org.springframework.lang.NonNull;
|
||||||
import org.springframework.stereotype.Component;
|
//import org.springframework.stereotype.Component;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
//import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionDefinition;
|
//import org.springframework.transaction.TransactionDefinition;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
//import org.springframework.transaction.TransactionStatus;
|
||||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
//import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||||
import org.springframework.ui.ModelMap;
|
//import org.springframework.ui.ModelMap;
|
||||||
import org.springframework.web.context.request.WebRequest;
|
//import org.springframework.web.context.request.WebRequest;
|
||||||
import org.springframework.web.context.request.WebRequestInterceptor;
|
//import org.springframework.web.context.request.WebRequestInterceptor;
|
||||||
|
//
|
||||||
import javax.management.InvalidApplicationException;
|
//import javax.management.InvalidApplicationException;
|
||||||
import javax.persistence.EntityManager;
|
//import javax.persistence.EntityManager;
|
||||||
import javax.persistence.PersistenceContext;
|
//import javax.persistence.PersistenceContext;
|
||||||
import javax.persistence.Tuple;
|
//import javax.persistence.Tuple;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
//import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
//import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.Root;
|
//import javax.persistence.criteria.Root;
|
||||||
import java.time.Instant;
|
//import java.time.Instant;
|
||||||
import java.util.List;
|
//import java.util.List;
|
||||||
import java.util.UUID;
|
//import java.util.UUID;
|
||||||
|
//
|
||||||
@Component
|
//@Component
|
||||||
public class UserInterceptor implements WebRequestInterceptor {
|
//public class UserInterceptor implements WebRequestInterceptor {
|
||||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserInterceptor.class));
|
// private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserInterceptor.class));
|
||||||
private final UserScope userScope;
|
// private final UserScope userScope;
|
||||||
private final ClaimExtractor claimExtractor;
|
// private final ClaimExtractor claimExtractor;
|
||||||
private final CurrentPrincipalResolver currentPrincipalResolver;
|
// private final CurrentPrincipalResolver currentPrincipalResolver;
|
||||||
private final LocaleService localeService;
|
// private final LocaleService localeService;
|
||||||
private final PlatformTransactionManager transactionManager;
|
// private final PlatformTransactionManager transactionManager;
|
||||||
private final UserInterceptorCacheService userInterceptorCacheService;
|
// private final UserInterceptorCacheService userInterceptorCacheService;
|
||||||
@PersistenceContext
|
// @PersistenceContext
|
||||||
public EntityManager entityManager;
|
// public EntityManager entityManager;
|
||||||
|
//
|
||||||
@Autowired
|
// @Autowired
|
||||||
public UserInterceptor(
|
// public UserInterceptor(
|
||||||
UserScope userScope,
|
// UserScope userScope,
|
||||||
LocaleService localeService,
|
// LocaleService localeService,
|
||||||
ClaimExtractor claimExtractor,
|
// ClaimExtractor claimExtractor,
|
||||||
CurrentPrincipalResolver currentPrincipalResolver,
|
// CurrentPrincipalResolver currentPrincipalResolver,
|
||||||
PlatformTransactionManager transactionManager,
|
// PlatformTransactionManager transactionManager,
|
||||||
UserInterceptorCacheService userInterceptorCacheService
|
// UserInterceptorCacheService userInterceptorCacheService
|
||||||
) {
|
// ) {
|
||||||
this.userScope = userScope;
|
// this.userScope = userScope;
|
||||||
this.localeService = localeService;
|
// this.localeService = localeService;
|
||||||
this.currentPrincipalResolver = currentPrincipalResolver;
|
// this.currentPrincipalResolver = currentPrincipalResolver;
|
||||||
this.claimExtractor = claimExtractor;
|
// this.claimExtractor = claimExtractor;
|
||||||
this.transactionManager = transactionManager;
|
// this.transactionManager = transactionManager;
|
||||||
this.userInterceptorCacheService = userInterceptorCacheService;
|
// this.userInterceptorCacheService = userInterceptorCacheService;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void preHandle(WebRequest request) throws InvalidApplicationException {
|
// public void preHandle(WebRequest request) throws InvalidApplicationException {
|
||||||
UUID userId = null;
|
// UUID userId = null;
|
||||||
if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) {
|
// if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) {
|
||||||
String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal());
|
// String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal());
|
||||||
|
//
|
||||||
UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId));
|
// UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId));
|
||||||
if (cacheValue != null) {
|
// if (cacheValue != null) {
|
||||||
userId = cacheValue.getUserId();
|
// userId = cacheValue.getUserId();
|
||||||
} else {
|
// } else {
|
||||||
userId = this.getUserIdFromDatabase(subjectId);
|
// userId = this.getUserIdFromDatabase(subjectId);
|
||||||
if (userId == null) userId = this.createUser(subjectId);
|
// if (userId == null) userId = this.createUser(subjectId);
|
||||||
|
//
|
||||||
this.userInterceptorCacheService.put(new UserInterceptorCacheService.UserInterceptorCacheValue(subjectId, userId));
|
// this.userInterceptorCacheService.put(new UserInterceptorCacheService.UserInterceptorCacheValue(subjectId, userId));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
this.userScope.setUserId(userId);
|
// this.userScope.setUserId(userId);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private UUID getUserIdFromDatabase(String subjectId) throws InvalidApplicationException {
|
// private UUID getUserIdFromDatabase(String subjectId) throws InvalidApplicationException {
|
||||||
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
|
// CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
|
||||||
CriteriaQuery<Tuple> query = criteriaBuilder.createQuery(Tuple.class);
|
// CriteriaQuery<Tuple> query = criteriaBuilder.createQuery(Tuple.class);
|
||||||
Root<UserEntity> root = query.from(UserEntity.class);
|
// Root<UserEntity> root = query.from(UserEntity.class);
|
||||||
query.where(
|
// query.where(
|
||||||
criteriaBuilder.and(
|
// criteriaBuilder.and(
|
||||||
// criteriaBuilder.equal(root.get(UserEntity._subjectId), subjectId),
|
//// criteriaBuilder.equal(root.get(UserEntity._subjectId), subjectId),
|
||||||
criteriaBuilder.equal(root.get(UserEntity._isActive), IsActive.Active)
|
// criteriaBuilder.equal(root.get(UserEntity._isActive), IsActive.Active)
|
||||||
));
|
// ));
|
||||||
|
//
|
||||||
query.multiselect(root.get(UserEntity._id).alias(UserEntity._id));
|
// query.multiselect(root.get(UserEntity._id).alias(UserEntity._id));
|
||||||
|
//
|
||||||
List<Tuple> results = this.entityManager.createQuery(query).getResultList();
|
// List<Tuple> results = this.entityManager.createQuery(query).getResultList();
|
||||||
if (results.size() == 1) {
|
// if (results.size() == 1) {
|
||||||
Object o;
|
// Object o;
|
||||||
try {
|
// try {
|
||||||
o = results.get(0).get(UserEntity._id);
|
// o = results.get(0).get(UserEntity._id);
|
||||||
} catch (IllegalArgumentException e) {
|
// } catch (IllegalArgumentException e) {
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
if (o == null) return null;
|
// if (o == null) return null;
|
||||||
try {
|
// try {
|
||||||
return UUID.class.cast(o);
|
// return UUID.class.cast(o);
|
||||||
} catch (ClassCastException e) {
|
// } catch (ClassCastException e) {
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private UUID createUser(String subjectId) {
|
// private UUID createUser(String subjectId) {
|
||||||
String name = this.claimExtractor.name(this.currentPrincipalResolver.currentPrincipal());
|
// String name = this.claimExtractor.name(this.currentPrincipalResolver.currentPrincipal());
|
||||||
String familyName = this.claimExtractor.familyName(this.currentPrincipalResolver.currentPrincipal());
|
// String familyName = this.claimExtractor.familyName(this.currentPrincipalResolver.currentPrincipal());
|
||||||
if (name == null) name = subjectId;
|
// if (name == null) name = subjectId;
|
||||||
UserEntity user = new UserEntity();
|
// UserEntity user = new UserEntity();
|
||||||
user.setId(UUID.randomUUID());
|
// user.setId(UUID.randomUUID());
|
||||||
user.setCreatedAt(Instant.now());
|
// user.setCreatedAt(Instant.now());
|
||||||
user.setUpdatedAt(Instant.now());
|
// user.setUpdatedAt(Instant.now());
|
||||||
user.setName(name);
|
// user.setName(name);
|
||||||
// user.setLastName(familyName == null ? name : familyName);
|
//// user.setLastName(familyName == null ? name : familyName);
|
||||||
user.setIsActive(IsActive.Active);
|
// user.setIsActive(IsActive.Active);
|
||||||
// user.setSubjectId(subjectId);
|
//// user.setSubjectId(subjectId);
|
||||||
// user.setCulture(this.localeService.cultureName());
|
//// user.setCulture(this.localeService.cultureName());
|
||||||
// user.setTimezone(this.localeService.timezoneName());
|
//// user.setTimezone(this.localeService.timezoneName());
|
||||||
// user.setLanguage(this.localeService.language());
|
//// user.setLanguage(this.localeService.language());
|
||||||
|
//
|
||||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
// DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||||
definition.setName(UUID.randomUUID().toString());
|
// definition.setName(UUID.randomUUID().toString());
|
||||||
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
|
// definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
|
||||||
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
// definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||||
TransactionStatus status = null;
|
// TransactionStatus status = null;
|
||||||
try {
|
// try {
|
||||||
status = transactionManager.getTransaction(definition);
|
// status = transactionManager.getTransaction(definition);
|
||||||
this.entityManager.persist(user);
|
// this.entityManager.persist(user);
|
||||||
|
//
|
||||||
this.entityManager.flush();
|
// this.entityManager.flush();
|
||||||
transactionManager.commit(status);
|
// transactionManager.commit(status);
|
||||||
} catch (Exception ex) {
|
// } catch (Exception ex) {
|
||||||
if (status != null) transactionManager.rollback(status);
|
// if (status != null) transactionManager.rollback(status);
|
||||||
throw ex;
|
// throw ex;
|
||||||
}
|
// }
|
||||||
return user.getId();
|
// return user.getId();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void postHandle(@NonNull WebRequest request, ModelMap model) {
|
// public void postHandle(@NonNull WebRequest request, ModelMap model) {
|
||||||
this.userScope.setUserId(null);
|
// this.userScope.setUserId(null);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void afterCompletion(@NonNull WebRequest request, Exception ex) {
|
// public void afterCompletion(@NonNull WebRequest request, Exception ex) {
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package gr.cite.notification.web.scope.user;
|
//package gr.cite.notification.web.scope.user;
|
||||||
|
//
|
||||||
import gr.cite.tools.cache.CacheOptions;
|
//import gr.cite.tools.cache.CacheOptions;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
//import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Configuration;
|
//import org.springframework.context.annotation.Configuration;
|
||||||
|
//
|
||||||
@Configuration
|
//@Configuration
|
||||||
@ConfigurationProperties(prefix = "cache.user-by-subject-id")
|
//@ConfigurationProperties(prefix = "cache.user-by-subject-id")
|
||||||
public class UserInterceptorCacheOptions extends CacheOptions {
|
//public class UserInterceptorCacheOptions extends CacheOptions {
|
||||||
}
|
//}
|
||||||
|
|
|
@ -1,77 +1,77 @@
|
||||||
package gr.cite.notification.web.scope.user;
|
//package gr.cite.notification.web.scope.user;
|
||||||
|
//
|
||||||
import gr.cite.notification.convention.ConventionService;
|
//import gr.cite.notification.convention.ConventionService;
|
||||||
import gr.cite.notification.event.UserTouchedEvent;
|
//import gr.cite.notification.event.UserTouchedEvent;
|
||||||
import gr.cite.tools.cache.CacheService;
|
//import gr.cite.tools.cache.CacheService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
//import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.event.EventListener;
|
//import org.springframework.context.event.EventListener;
|
||||||
import org.springframework.stereotype.Service;
|
//import org.springframework.stereotype.Service;
|
||||||
|
//
|
||||||
import java.util.HashMap;
|
//import java.util.HashMap;
|
||||||
import java.util.UUID;
|
//import java.util.UUID;
|
||||||
|
//
|
||||||
@Service
|
//@Service
|
||||||
public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> {
|
//public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> {
|
||||||
|
//
|
||||||
public static class UserInterceptorCacheValue {
|
// public static class UserInterceptorCacheValue {
|
||||||
|
//
|
||||||
public UserInterceptorCacheValue() {
|
// public UserInterceptorCacheValue() {
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public UserInterceptorCacheValue(String subjectId, UUID userId) {
|
// public UserInterceptorCacheValue(String subjectId, UUID userId) {
|
||||||
this.subjectId = subjectId;
|
// this.subjectId = subjectId;
|
||||||
this.userId = userId;
|
// this.userId = userId;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private String subjectId;
|
// private String subjectId;
|
||||||
|
//
|
||||||
public String getSubjectId() {
|
// public String getSubjectId() {
|
||||||
return subjectId;
|
// return subjectId;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public void setSubjectId(String subjectId) {
|
// public void setSubjectId(String subjectId) {
|
||||||
this.subjectId = subjectId;
|
// this.subjectId = subjectId;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private UUID userId;
|
// private UUID userId;
|
||||||
|
//
|
||||||
public UUID getUserId() {
|
// public UUID getUserId() {
|
||||||
return userId;
|
// return userId;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public void setUserId(UUID userId) {
|
// public void setUserId(UUID userId) {
|
||||||
this.userId = userId;
|
// this.userId = userId;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private final ConventionService conventionService;
|
// private final ConventionService conventionService;
|
||||||
|
//
|
||||||
@Autowired
|
// @Autowired
|
||||||
public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) {
|
// public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) {
|
||||||
super(options);
|
// super(options);
|
||||||
this.conventionService = conventionService;
|
// this.conventionService = conventionService;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@EventListener
|
// @EventListener
|
||||||
public void handleUserTouchedEvent(UserTouchedEvent event) {
|
// public void handleUserTouchedEvent(UserTouchedEvent event) {
|
||||||
if (!this.conventionService.isNullOrEmpty(event.getSubjectId())) this.evict(this.buildKey(event.getSubjectId()));
|
// if (!this.conventionService.isNullOrEmpty(event.getSubjectId())) this.evict(this.buildKey(event.getSubjectId()));
|
||||||
if (!this.conventionService.isNullOrEmpty(event.getPreviousSubjectId())) this.evict(this.buildKey(event.getPreviousSubjectId()));
|
// if (!this.conventionService.isNullOrEmpty(event.getPreviousSubjectId())) this.evict(this.buildKey(event.getPreviousSubjectId()));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected Class<UserInterceptorCacheValue> valueClass() {
|
// protected Class<UserInterceptorCacheValue> valueClass() {
|
||||||
return UserInterceptorCacheValue.class;
|
// return UserInterceptorCacheValue.class;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public String keyOf(UserInterceptorCacheValue value) {
|
// public String keyOf(UserInterceptorCacheValue value) {
|
||||||
return this.buildKey(value.getSubjectId());
|
// return this.buildKey(value.getSubjectId());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
public String buildKey(String subject) {
|
// public String buildKey(String subject) {
|
||||||
return this.generateKey(new HashMap<>() {{
|
// return this.generateKey(new HashMap<>() {{
|
||||||
put("$subject$", subject);
|
// put("$subject$", subject);
|
||||||
}});
|
// }});
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
|
@ -19,18 +19,12 @@ idpclient:
|
||||||
- type: email
|
- type: email
|
||||||
Roles:
|
Roles:
|
||||||
- type: resource_access
|
- type: resource_access
|
||||||
path: intelcomp-sti-viewer-dev.roles
|
path: dmp_web.roles
|
||||||
- type: authorities
|
|
||||||
filterBy: "(.*):::TenantCode::"
|
|
||||||
extractByExpression: "(.*):(.*)"
|
|
||||||
extractExpressionValue: "[[g1]]"
|
|
||||||
Scope:
|
Scope:
|
||||||
- type: scope
|
- type: scope
|
||||||
AccessToken:
|
AccessToken:
|
||||||
- type: x-access-token
|
- type: x-access-token
|
||||||
visibility: SENSITIVE
|
visibility: SENSITIVE
|
||||||
Tenant:
|
|
||||||
- type: x-tenant
|
|
||||||
IssuedAt:
|
IssuedAt:
|
||||||
- type: iat
|
- type: iat
|
||||||
Issuer:
|
Issuer:
|
||||||
|
@ -43,8 +37,3 @@ idpclient:
|
||||||
- type: azp
|
- type: azp
|
||||||
Authorities:
|
Authorities:
|
||||||
- type: authorities
|
- type: authorities
|
||||||
TenantCodes:
|
|
||||||
- type: authorities
|
|
||||||
filterBy: "(.*):(.*)"
|
|
||||||
extractByExpression: "(.*):(.*)"
|
|
||||||
extractExpressionValue: "[[g2]]"
|
|
||||||
|
|
|
@ -19,18 +19,12 @@ idpclient:
|
||||||
- type: email
|
- type: email
|
||||||
Roles:
|
Roles:
|
||||||
- type: resource_access
|
- type: resource_access
|
||||||
path: intelcomp-sti-viewer-dev.roles
|
path: dmp_web.roles
|
||||||
- type: authorities
|
|
||||||
filterBy: "(.*):::TenantCode::"
|
|
||||||
extractByExpression: "(.*):(.*)"
|
|
||||||
extractExpressionValue: "[[g1]]"
|
|
||||||
Scope:
|
Scope:
|
||||||
- type: scope
|
- type: scope
|
||||||
AccessToken:
|
AccessToken:
|
||||||
- type: x-access-token
|
- type: x-access-token
|
||||||
visibility: SENSITIVE
|
visibility: SENSITIVE
|
||||||
Tenant:
|
|
||||||
- type: x-tenant
|
|
||||||
IssuedAt:
|
IssuedAt:
|
||||||
- type: iat
|
- type: iat
|
||||||
Issuer:
|
Issuer:
|
||||||
|
@ -43,8 +37,3 @@ idpclient:
|
||||||
- type: azp
|
- type: azp
|
||||||
Authorities:
|
Authorities:
|
||||||
- type: authorities
|
- type: authorities
|
||||||
TenantCodes:
|
|
||||||
- type: authorities
|
|
||||||
filterBy: "(.*):(.*)"
|
|
||||||
extractByExpression: "(.*):(.*)"
|
|
||||||
extractExpressionValue: "[[g2]]"
|
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package gr.cite.notification.common.lock;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class LockByKeyManager {
|
||||||
|
|
||||||
|
private static class LockWrapper {
|
||||||
|
private final ReentrantLock lock = new ReentrantLock();
|
||||||
|
private final AtomicInteger numberOfThreadsInQueue = new AtomicInteger(1);
|
||||||
|
|
||||||
|
private LockWrapper addThreadInQueue() {
|
||||||
|
numberOfThreadsInQueue.incrementAndGet();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int removeThreadFromQueue() {
|
||||||
|
return numberOfThreadsInQueue.decrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ConcurrentHashMap<String, LockWrapper> locks = new ConcurrentHashMap<String, LockWrapper>();
|
||||||
|
|
||||||
|
public void lock(String key) {
|
||||||
|
LockWrapper lockWrapper = locks.compute(key, (k, v) -> v == null ? new LockWrapper() : v.addThreadInQueue());
|
||||||
|
lockWrapper.lock.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean tryLock(String key, long timeout, TimeUnit unit) throws InterruptedException {
|
||||||
|
LockWrapper lockWrapper = null;
|
||||||
|
try {
|
||||||
|
lockWrapper = locks.compute(key, (k, v) -> v == null ? new LockWrapper() : v.addThreadInQueue());
|
||||||
|
return lockWrapper.lock.tryLock(timeout, unit);
|
||||||
|
} catch (Exception ex){
|
||||||
|
if (lockWrapper != null && lockWrapper.removeThreadFromQueue() == 0) {
|
||||||
|
// NB : We pass in the specific value to remove to handle the case where another thread would queue right before the removal
|
||||||
|
locks.remove(key, lockWrapper);
|
||||||
|
}
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unlock(String key) {
|
||||||
|
LockWrapper lockWrapper = locks.get(key);
|
||||||
|
lockWrapper.lock.unlock();
|
||||||
|
if (lockWrapper.removeThreadFromQueue() == 0) {
|
||||||
|
// NB : We pass in the specific value to remove to handle the case where another thread would queue right before the removal
|
||||||
|
locks.remove(key, lockWrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package gr.cite.notification.common.types.user;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class AdditionalInfoEntity {
|
||||||
|
private String avatarUrl;
|
||||||
|
private String timezone;
|
||||||
|
private String culture;
|
||||||
|
private String language;
|
||||||
|
private String roleOrganization;
|
||||||
|
private UUID organizationId;
|
||||||
|
|
||||||
|
public String getAvatarUrl() {
|
||||||
|
return avatarUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatarUrl(String avatarUrl) {
|
||||||
|
this.avatarUrl = avatarUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTimezone() {
|
||||||
|
return timezone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimezone(String timezone) {
|
||||||
|
this.timezone = timezone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCulture() {
|
||||||
|
return culture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCulture(String culture) {
|
||||||
|
this.culture = culture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLanguage() {
|
||||||
|
return language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLanguage(String language) {
|
||||||
|
this.language = language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getOrganizationId() {
|
||||||
|
return organizationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrganizationId(UUID organizationId) {
|
||||||
|
this.organizationId = organizationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRoleOrganization() {
|
||||||
|
return roleOrganization;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoleOrganization(String roleOrganization) {
|
||||||
|
this.roleOrganization = roleOrganization;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package gr.cite.notification.data;
|
||||||
|
|
||||||
|
|
||||||
|
import gr.cite.notification.data.tenant.TenantScopedBaseEntity;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "\"UserCredential\"")
|
||||||
|
public class UserCredentialEntity extends TenantScopedBaseEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false)
|
||||||
|
private UUID id;
|
||||||
|
public final static String _id = "id";
|
||||||
|
|
||||||
|
@Column(name = "\"user\"", columnDefinition = "uuid", nullable = false)
|
||||||
|
private UUID userId;
|
||||||
|
public final static String _userId = "userId";
|
||||||
|
|
||||||
|
@Column(name = "\"external_id\"", length = UserCredentialEntity._externalIdLength, nullable = false)
|
||||||
|
private String externalId;
|
||||||
|
public final static String _externalId = "externalId";
|
||||||
|
public final static int _externalIdLength = 512;
|
||||||
|
|
||||||
|
@Column(name = "created_at", nullable = false)
|
||||||
|
private Instant createdAt;
|
||||||
|
|
||||||
|
public static final String _createdAt = "createdAt";
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(UUID userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExternalId() {
|
||||||
|
return externalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExternalId(String externalId) {
|
||||||
|
this.externalId = externalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(Instant createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package gr.cite.notification.data;
|
||||||
|
|
||||||
|
|
||||||
|
import gr.cite.notification.data.tenant.TenantScopedBaseEntity;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "\"UserRole\"")
|
||||||
|
public class UserRoleEntity extends TenantScopedBaseEntity {
|
||||||
|
@Id
|
||||||
|
@Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false)
|
||||||
|
private UUID id;
|
||||||
|
public static final String _id = "id";
|
||||||
|
|
||||||
|
@Column(name = "role", length = UserRoleEntity._roleLength, nullable = false)
|
||||||
|
private String role;
|
||||||
|
public static final String _role = "role";
|
||||||
|
public static final int _roleLength = 512;
|
||||||
|
|
||||||
|
@Column(name = "\"user\"", nullable = false)
|
||||||
|
private UUID userId;
|
||||||
|
public static final String _userId = "userId";
|
||||||
|
|
||||||
|
|
||||||
|
@Column(name = "created_at", nullable = false)
|
||||||
|
private Instant createdAt;
|
||||||
|
|
||||||
|
public static final String _createdAt = "createdAt";
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRole() {
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRole(String role) {
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(UUID userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(Instant createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package gr.cite.notification.model;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UserCredential {
|
||||||
|
private UUID id;
|
||||||
|
public static final String _id = "id";
|
||||||
|
|
||||||
|
private String externalId;
|
||||||
|
public static final String _externalId = "externalId";
|
||||||
|
|
||||||
|
private User user;
|
||||||
|
public static final String _user = "user";
|
||||||
|
|
||||||
|
private Instant createdAt;
|
||||||
|
|
||||||
|
public static final String _createdAt = "createdAt";
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExternalId() {
|
||||||
|
return externalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExternalId(String externalId) {
|
||||||
|
this.externalId = externalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(Instant createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package gr.cite.notification.model;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UserRole {
|
||||||
|
private UUID id;
|
||||||
|
public static final String _id = "id";
|
||||||
|
|
||||||
|
private String role;
|
||||||
|
public static final String _role = "role";
|
||||||
|
|
||||||
|
private User user;
|
||||||
|
public static final String _user = "user";
|
||||||
|
|
||||||
|
private Instant createdAt;
|
||||||
|
|
||||||
|
public static final String _createdAt = "createdAt";
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(UUID id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRole() {
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRole(String role) {
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(Instant createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,9 +30,11 @@ public class UserContactInfoQuery extends QueryBase<UserContactInfoEntity> {
|
||||||
|
|
||||||
private Collection<UUID> ids;
|
private Collection<UUID> ids;
|
||||||
private Collection<UUID> userIds;
|
private Collection<UUID> userIds;
|
||||||
|
private Collection<UUID> excludedUserIds;
|
||||||
private Collection<UUID> tenantIds;
|
private Collection<UUID> tenantIds;
|
||||||
private Collection<IsActive> isActives;
|
private Collection<IsActive> isActives;
|
||||||
private Collection<ContactInfoType> type;
|
private Collection<ContactInfoType> type;
|
||||||
|
private Collection<String> values;
|
||||||
private UserQuery userQuery;
|
private UserQuery userQuery;
|
||||||
|
|
||||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||||
|
@ -78,6 +80,21 @@ public class UserContactInfoQuery extends QueryBase<UserContactInfoEntity> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UserContactInfoQuery excludedUserIds(Collection<UUID> values) {
|
||||||
|
this.excludedUserIds = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserContactInfoQuery excludedUserIds(UUID value) {
|
||||||
|
this.excludedUserIds = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserContactInfoQuery excludedUserIds(UUID... value) {
|
||||||
|
this.excludedUserIds = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public UserContactInfoQuery tenantIds(UUID value) {
|
public UserContactInfoQuery tenantIds(UUID value) {
|
||||||
this.tenantIds = List.of(value);
|
this.tenantIds = List.of(value);
|
||||||
return this;
|
return this;
|
||||||
|
@ -123,6 +140,21 @@ public class UserContactInfoQuery extends QueryBase<UserContactInfoEntity> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UserContactInfoQuery values(String value) {
|
||||||
|
this.values = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserContactInfoQuery values(String... value) {
|
||||||
|
this.values = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserContactInfoQuery values(Collection<String> values) {
|
||||||
|
this.values = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public UserContactInfoQuery userSubQuery(UserQuery subQuery) {
|
public UserContactInfoQuery userSubQuery(UserQuery subQuery) {
|
||||||
this.userQuery = subQuery;
|
this.userQuery = subQuery;
|
||||||
return this;
|
return this;
|
||||||
|
@ -135,7 +167,8 @@ public class UserContactInfoQuery extends QueryBase<UserContactInfoEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Boolean isFalseQuery() {
|
protected Boolean isFalseQuery() {
|
||||||
return this.isEmpty(this.userIds) || this.isEmpty(this.tenantIds) || this.isEmpty(this.isActives) || this.isEmpty(this.type) || this.isFalseQuery(this.userQuery);
|
return this.isEmpty(this.userIds) || this.isEmpty(this.excludedUserIds) || this.isEmpty(this.tenantIds) || this.isEmpty(this.isActives)
|
||||||
|
|| this.isEmpty(this.type) || this.isEmpty(this.excludedUserIds) || this.isFalseQuery(this.userQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -170,6 +203,12 @@ public class UserContactInfoQuery extends QueryBase<UserContactInfoEntity> {
|
||||||
for (UUID item : this.userIds) inClause.value(item);
|
for (UUID item : this.userIds) inClause.value(item);
|
||||||
predicates.add(inClause);
|
predicates.add(inClause);
|
||||||
}
|
}
|
||||||
|
if (this.excludedUserIds != null) {
|
||||||
|
CriteriaBuilder.In<UUID> notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserContactInfoEntity._userId));
|
||||||
|
for (UUID item : this.excludedUserIds)
|
||||||
|
notInClause.value(item);
|
||||||
|
predicates.add(notInClause.not());
|
||||||
|
}
|
||||||
if (this.tenantIds != null) {
|
if (this.tenantIds != null) {
|
||||||
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserContactInfoEntity._tenantId));
|
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserContactInfoEntity._tenantId));
|
||||||
for (UUID item : this.tenantIds) inClause.value(item);
|
for (UUID item : this.tenantIds) inClause.value(item);
|
||||||
|
@ -180,6 +219,12 @@ public class UserContactInfoQuery extends QueryBase<UserContactInfoEntity> {
|
||||||
for (ContactInfoType item : this.type) inClause.value(item);
|
for (ContactInfoType item : this.type) inClause.value(item);
|
||||||
predicates.add(inClause);
|
predicates.add(inClause);
|
||||||
}
|
}
|
||||||
|
if (this.values != null) {
|
||||||
|
CriteriaBuilder.In<String> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserContactInfoEntity._value));
|
||||||
|
for (String item : this.values)
|
||||||
|
inClause.value(item);
|
||||||
|
predicates.add(inClause);
|
||||||
|
}
|
||||||
if (this.userQuery != null) {
|
if (this.userQuery != null) {
|
||||||
Subquery<UserEntity> subQuery = queryContext.Query.subquery(this.userQuery.entityClass());
|
Subquery<UserEntity> subQuery = queryContext.Query.subquery(this.userQuery.entityClass());
|
||||||
this.applySubQuery(this.userQuery, queryContext.CriteriaBuilder, subQuery);
|
this.applySubQuery(this.userQuery, queryContext.CriteriaBuilder, subQuery);
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
package gr.cite.notification.query;
|
||||||
|
|
||||||
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||||
|
import gr.cite.notification.authorization.AuthorizationFlags;
|
||||||
|
import gr.cite.notification.authorization.Permission;
|
||||||
|
import gr.cite.notification.common.scope.user.UserScope;
|
||||||
|
import gr.cite.notification.data.UserCredentialEntity;
|
||||||
|
import gr.cite.notification.model.UserCredential;
|
||||||
|
import gr.cite.tools.data.query.FieldResolver;
|
||||||
|
import gr.cite.tools.data.query.QueryBase;
|
||||||
|
import gr.cite.tools.data.query.QueryContext;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.persistence.Tuple;
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import javax.persistence.criteria.Predicate;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class UserCredentialQuery extends QueryBase<UserCredentialEntity> {
|
||||||
|
private Collection<UUID> ids;
|
||||||
|
private Collection<UUID> excludedIds;
|
||||||
|
private Collection<UUID> userIds;
|
||||||
|
private Collection<String> externalIds;
|
||||||
|
|
||||||
|
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||||
|
|
||||||
|
private final UserScope userScope;
|
||||||
|
private final AuthorizationService authService;
|
||||||
|
public UserCredentialQuery(UserScope userScope, AuthorizationService authService) {
|
||||||
|
this.userScope = userScope;
|
||||||
|
this.authService = authService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery ids(UUID value) {
|
||||||
|
this.ids = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery ids(UUID... value) {
|
||||||
|
this.ids = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery ids(Collection<UUID> values) {
|
||||||
|
this.ids = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery excludedIds(Collection<UUID> values) {
|
||||||
|
this.excludedIds = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery excludedIds(UUID value) {
|
||||||
|
this.excludedIds = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery excludedIds(UUID... value) {
|
||||||
|
this.excludedIds = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery userIds(UUID value) {
|
||||||
|
this.userIds = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery userIds(UUID... value) {
|
||||||
|
this.userIds = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery userIds(Collection<UUID> values) {
|
||||||
|
this.userIds = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery externalIds(String value) {
|
||||||
|
this.externalIds = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery externalIds(String... value) {
|
||||||
|
this.externalIds = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery externalIds(Collection<String> values) {
|
||||||
|
this.externalIds = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserCredentialQuery authorize(EnumSet<AuthorizationFlags> values) {
|
||||||
|
this.authorize = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Boolean isFalseQuery() {
|
||||||
|
return
|
||||||
|
this.isEmpty(this.ids) ||
|
||||||
|
this.isEmpty(this.userIds) ||
|
||||||
|
this.isEmpty(this.externalIds) ||
|
||||||
|
this.isEmpty(this.excludedIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<UserCredentialEntity> entityClass() {
|
||||||
|
return UserCredentialEntity.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected <X, Y> Predicate applyAuthZ(QueryContext<X, Y> queryContext) {
|
||||||
|
if (this.authorize.contains(AuthorizationFlags.None)) return null;
|
||||||
|
if (this.authorize.contains(AuthorizationFlags.Permission) && this.authService.authorize(Permission.BrowseUser)) return null;
|
||||||
|
UUID userId;
|
||||||
|
if (this.authorize.contains(AuthorizationFlags.Owner)) userId = this.userScope.getUserIdSafe();
|
||||||
|
else userId = null;
|
||||||
|
|
||||||
|
List<Predicate> predicates = new ArrayList<>();
|
||||||
|
if (userId != null) {
|
||||||
|
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(UserCredentialEntity._userId)).value(userId));
|
||||||
|
}
|
||||||
|
if (!predicates.isEmpty()) {
|
||||||
|
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
|
||||||
|
return queryContext.CriteriaBuilder.and(predicatesArray);
|
||||||
|
} else {
|
||||||
|
return queryContext.CriteriaBuilder.or(); //Creates a false query
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
|
||||||
|
List<Predicate> predicates = new ArrayList<>();
|
||||||
|
if (this.ids != null) {
|
||||||
|
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserCredentialEntity._id));
|
||||||
|
for (UUID item : this.ids)
|
||||||
|
inClause.value(item);
|
||||||
|
predicates.add(inClause);
|
||||||
|
}
|
||||||
|
if (this.userIds != null) {
|
||||||
|
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserCredentialEntity._userId));
|
||||||
|
for (UUID item : this.userIds)
|
||||||
|
inClause.value(item);
|
||||||
|
predicates.add(inClause);
|
||||||
|
}
|
||||||
|
if (this.excludedIds != null) {
|
||||||
|
CriteriaBuilder.In<UUID> notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserCredentialEntity._id));
|
||||||
|
for (UUID item : this.excludedIds)
|
||||||
|
notInClause.value(item);
|
||||||
|
predicates.add(notInClause.not());
|
||||||
|
}
|
||||||
|
if (this.externalIds != null) {
|
||||||
|
CriteriaBuilder.In<String> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserCredentialEntity._externalId));
|
||||||
|
for (String item : this.externalIds)
|
||||||
|
inClause.value(item);
|
||||||
|
predicates.add(inClause);
|
||||||
|
}
|
||||||
|
if (!predicates.isEmpty()) {
|
||||||
|
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
|
||||||
|
return queryContext.CriteriaBuilder.and(predicatesArray);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String fieldNameOf(FieldResolver item) {
|
||||||
|
if (item.match(UserCredential._id)) return UserCredentialEntity._id;
|
||||||
|
else if (item.match(UserCredential._externalId)) return UserCredentialEntity._externalId;
|
||||||
|
else if (item.prefix(UserCredential._user)) return UserCredentialEntity._userId;
|
||||||
|
else if (item.match(UserCredential._user)) return UserCredentialEntity._userId;
|
||||||
|
else if (item.match(UserCredential._createdAt) ) return UserCredentialEntity._createdAt;
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected UserCredentialEntity convert(Tuple tuple, Set<String> columns) {
|
||||||
|
UserCredentialEntity item = new UserCredentialEntity();
|
||||||
|
item.setId(QueryBase.convertSafe(tuple, columns, UserCredentialEntity._id, UUID.class));
|
||||||
|
item.setExternalId(QueryBase.convertSafe(tuple, columns, UserCredentialEntity._externalId, String.class));
|
||||||
|
item.setUserId(QueryBase.convertSafe(tuple, columns, UserCredentialEntity._userId, UUID.class));
|
||||||
|
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, UserCredentialEntity._createdAt, Instant.class));
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,194 @@
|
||||||
|
package gr.cite.notification.query;
|
||||||
|
|
||||||
|
|
||||||
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||||
|
import gr.cite.notification.authorization.AuthorizationFlags;
|
||||||
|
import gr.cite.notification.authorization.Permission;
|
||||||
|
import gr.cite.notification.common.scope.user.UserScope;
|
||||||
|
import gr.cite.notification.data.UserRoleEntity;
|
||||||
|
import gr.cite.notification.model.UserRole;
|
||||||
|
import gr.cite.tools.data.query.FieldResolver;
|
||||||
|
import gr.cite.tools.data.query.QueryBase;
|
||||||
|
import gr.cite.tools.data.query.QueryContext;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.persistence.Tuple;
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import javax.persistence.criteria.Predicate;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class UserRoleQuery extends QueryBase<UserRoleEntity> {
|
||||||
|
private Collection<UUID> ids;
|
||||||
|
private Collection<UUID> excludedIds;
|
||||||
|
private Collection<UUID> userIds;
|
||||||
|
private Collection<String> roles;
|
||||||
|
|
||||||
|
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||||
|
|
||||||
|
private final UserScope userScope;
|
||||||
|
private final AuthorizationService authService;
|
||||||
|
public UserRoleQuery(UserScope userScope, AuthorizationService authService) {
|
||||||
|
this.userScope = userScope;
|
||||||
|
this.authService = authService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery ids(UUID value) {
|
||||||
|
this.ids = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery ids(UUID... value) {
|
||||||
|
this.ids = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery ids(Collection<UUID> values) {
|
||||||
|
this.ids = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery excludedIds(Collection<UUID> values) {
|
||||||
|
this.excludedIds = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery excludedIds(UUID value) {
|
||||||
|
this.excludedIds = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery excludedIds(UUID... value) {
|
||||||
|
this.excludedIds = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery userIds(UUID value) {
|
||||||
|
this.userIds = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery userIds(UUID... value) {
|
||||||
|
this.userIds = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery userIds(Collection<UUID> values) {
|
||||||
|
this.userIds = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery roles(String value) {
|
||||||
|
this.roles = List.of(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery roles(String... value) {
|
||||||
|
this.roles = Arrays.asList(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery roles(Collection<String> values) {
|
||||||
|
this.roles = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRoleQuery authorize(EnumSet<AuthorizationFlags> values) {
|
||||||
|
this.authorize = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Boolean isFalseQuery() {
|
||||||
|
return
|
||||||
|
this.isEmpty(this.ids) ||
|
||||||
|
this.isEmpty(this.userIds) ||
|
||||||
|
this.isEmpty(this.roles) ||
|
||||||
|
this.isEmpty(this.excludedIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<UserRoleEntity> entityClass() {
|
||||||
|
return UserRoleEntity.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected <X, Y> Predicate applyAuthZ(QueryContext<X, Y> queryContext) {
|
||||||
|
if (this.authorize.contains(AuthorizationFlags.None)) return null;
|
||||||
|
if (this.authorize.contains(AuthorizationFlags.Permission) && this.authService.authorize(Permission.BrowseUser)) return null;
|
||||||
|
UUID userId;
|
||||||
|
if (this.authorize.contains(AuthorizationFlags.Owner)) userId = this.userScope.getUserIdSafe();
|
||||||
|
else userId = null;
|
||||||
|
|
||||||
|
List<Predicate> predicates = new ArrayList<>();
|
||||||
|
if (userId != null) {
|
||||||
|
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(UserRoleEntity._userId)).value(userId));
|
||||||
|
}
|
||||||
|
if (!predicates.isEmpty()) {
|
||||||
|
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
|
||||||
|
return queryContext.CriteriaBuilder.and(predicatesArray);
|
||||||
|
} else {
|
||||||
|
return queryContext.CriteriaBuilder.or(); //Creates a false query
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
|
||||||
|
List<Predicate> predicates = new ArrayList<>();
|
||||||
|
if (this.ids != null) {
|
||||||
|
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserRoleEntity._id));
|
||||||
|
for (UUID item : this.ids)
|
||||||
|
inClause.value(item);
|
||||||
|
predicates.add(inClause);
|
||||||
|
}
|
||||||
|
if (this.userIds != null) {
|
||||||
|
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserRoleEntity._userId));
|
||||||
|
for (UUID item : this.userIds)
|
||||||
|
inClause.value(item);
|
||||||
|
predicates.add(inClause);
|
||||||
|
}
|
||||||
|
if (this.excludedIds != null) {
|
||||||
|
CriteriaBuilder.In<UUID> notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserRoleEntity._id));
|
||||||
|
for (UUID item : this.excludedIds)
|
||||||
|
notInClause.value(item);
|
||||||
|
predicates.add(notInClause.not());
|
||||||
|
}
|
||||||
|
if (this.roles != null) {
|
||||||
|
CriteriaBuilder.In<String> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserRoleEntity._role));
|
||||||
|
for (String item : this.roles)
|
||||||
|
inClause.value(item);
|
||||||
|
predicates.add(inClause);
|
||||||
|
}
|
||||||
|
if (!predicates.isEmpty()) {
|
||||||
|
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
|
||||||
|
return queryContext.CriteriaBuilder.and(predicatesArray);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String fieldNameOf(FieldResolver item) {
|
||||||
|
if (item.match(UserRole._id)) return UserRoleEntity._id;
|
||||||
|
else if (item.match(UserRole._role)) return UserRoleEntity._role;
|
||||||
|
else if (item.prefix(UserRole._user)) return UserRoleEntity._userId;
|
||||||
|
else if (item.match(UserRole._user)) return UserRoleEntity._userId;
|
||||||
|
else if (item.match(UserRole._createdAt) ) return UserRoleEntity._createdAt;
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected UserRoleEntity convert(Tuple tuple, Set<String> columns) {
|
||||||
|
UserRoleEntity item = new UserRoleEntity();
|
||||||
|
item.setId(QueryBase.convertSafe(tuple, columns, UserRoleEntity._id, UUID.class));
|
||||||
|
item.setRole(QueryBase.convertSafe(tuple, columns, UserRoleEntity._role, String.class));
|
||||||
|
item.setUserId(QueryBase.convertSafe(tuple, columns, UserRoleEntity._userId, UUID.class));
|
||||||
|
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, UserRoleEntity._createdAt, Instant.class));
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -83,7 +83,7 @@ public class NotificationServiceTemplateImpl implements NotificationTemplateServ
|
||||||
public NotificationTemplate persist(NotificationTemplatePersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException {
|
public NotificationTemplate persist(NotificationTemplatePersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException {
|
||||||
logger.debug(new MapLogEntry("persisting notification template").And("model", model).And("fields", fields));
|
logger.debug(new MapLogEntry("persisting notification template").And("model", model).And("fields", fields));
|
||||||
|
|
||||||
// this.authorizationService.authorizeForce(Permission.EditNotificationTemplate); TODO
|
this.authorizationService.authorizeForce(Permission.EditNotificationTemplate);
|
||||||
|
|
||||||
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
|
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue