change idpclaims.yml and add user interceptor

This commit is contained in:
amentis 2024-01-02 11:06:10 +02:00
parent 1fb516c8ef
commit 28238c7a6d
20 changed files with 1425 additions and 270 deletions

View File

@ -3,7 +3,7 @@ package gr.cite.notification.web;
import gr.cite.notification.web.scope.tenant.TenantInterceptor;
import gr.cite.notification.web.scope.tenant.TenantScopeClaimInterceptor;
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.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

View File

@ -63,7 +63,7 @@ public class NotificationTemplateController {
public QueryResult<NotificationTemplate> query(@RequestBody NotificationTemplateLookup lookup) throws MyApplicationException, MyForbiddenException {
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);
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 {
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);
NotificationTemplate model = this.builderFactory.builder(NotificationTemplateBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.first());

View File

@ -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) {
}
}

View File

@ -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 {
}

View File

@ -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);
}
}

View File

@ -1,154 +1,154 @@
package gr.cite.notification.web.scope.user;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
import gr.cite.notification.common.enums.IsActive;
import gr.cite.notification.common.scope.user.UserScope;
import gr.cite.notification.data.UserEntity;
import gr.cite.notification.locale.LocaleService;
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.management.InvalidApplicationException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Tuple;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
@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 LocaleService localeService;
private final PlatformTransactionManager transactionManager;
private final UserInterceptorCacheService userInterceptorCacheService;
@PersistenceContext
public EntityManager entityManager;
@Autowired
public UserInterceptor(
UserScope userScope,
LocaleService localeService,
ClaimExtractor claimExtractor,
CurrentPrincipalResolver currentPrincipalResolver,
PlatformTransactionManager transactionManager,
UserInterceptorCacheService userInterceptorCacheService
) {
this.userScope = userScope;
this.localeService = localeService;
this.currentPrincipalResolver = currentPrincipalResolver;
this.claimExtractor = claimExtractor;
this.transactionManager = transactionManager;
this.userInterceptorCacheService = userInterceptorCacheService;
}
@Override
public void preHandle(WebRequest request) throws InvalidApplicationException {
UUID userId = null;
if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) {
String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal());
UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId));
if (cacheValue != null) {
userId = cacheValue.getUserId();
} else {
userId = this.getUserIdFromDatabase(subjectId);
if (userId == null) userId = this.createUser(subjectId);
this.userInterceptorCacheService.put(new UserInterceptorCacheService.UserInterceptorCacheValue(subjectId, userId));
}
}
this.userScope.setUserId(userId);
}
private UUID getUserIdFromDatabase(String subjectId) throws InvalidApplicationException {
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> query = criteriaBuilder.createQuery(Tuple.class);
Root<UserEntity> root = query.from(UserEntity.class);
query.where(
criteriaBuilder.and(
// criteriaBuilder.equal(root.get(UserEntity._subjectId), subjectId),
criteriaBuilder.equal(root.get(UserEntity._isActive), IsActive.Active)
));
query.multiselect(root.get(UserEntity._id).alias(UserEntity._id));
List<Tuple> results = this.entityManager.createQuery(query).getResultList();
if (results.size() == 1) {
Object o;
try {
o = results.get(0).get(UserEntity._id);
} catch (IllegalArgumentException e) {
return null;
}
if (o == null) return null;
try {
return UUID.class.cast(o);
} catch (ClassCastException e) {
return null;
}
}
return null;
}
private UUID createUser(String subjectId) {
String name = this.claimExtractor.name(this.currentPrincipalResolver.currentPrincipal());
String familyName = this.claimExtractor.familyName(this.currentPrincipalResolver.currentPrincipal());
if (name == null) name = subjectId;
UserEntity user = new UserEntity();
user.setId(UUID.randomUUID());
user.setCreatedAt(Instant.now());
user.setUpdatedAt(Instant.now());
user.setName(name);
// user.setLastName(familyName == null ? name : familyName);
user.setIsActive(IsActive.Active);
// user.setSubjectId(subjectId);
// user.setCulture(this.localeService.cultureName());
// user.setTimezone(this.localeService.timezoneName());
// user.setLanguage(this.localeService.language());
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);
this.entityManager.persist(user);
this.entityManager.flush();
transactionManager.commit(status);
} catch (Exception ex) {
if (status != null) transactionManager.rollback(status);
throw ex;
}
return user.getId();
}
@Override
public void postHandle(@NonNull WebRequest request, ModelMap model) {
this.userScope.setUserId(null);
}
@Override
public void afterCompletion(@NonNull WebRequest request, Exception ex) {
}
}
//package gr.cite.notification.web.scope.user;
//
//
//import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
//import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
//import gr.cite.notification.common.enums.IsActive;
//import gr.cite.notification.common.scope.user.UserScope;
//import gr.cite.notification.data.UserEntity;
//import gr.cite.notification.locale.LocaleService;
//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.management.InvalidApplicationException;
//import javax.persistence.EntityManager;
//import javax.persistence.PersistenceContext;
//import javax.persistence.Tuple;
//import javax.persistence.criteria.CriteriaBuilder;
//import javax.persistence.criteria.CriteriaQuery;
//import javax.persistence.criteria.Root;
//import java.time.Instant;
//import java.util.List;
//import java.util.UUID;
//
//@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 LocaleService localeService;
// private final PlatformTransactionManager transactionManager;
// private final UserInterceptorCacheService userInterceptorCacheService;
// @PersistenceContext
// public EntityManager entityManager;
//
// @Autowired
// public UserInterceptor(
// UserScope userScope,
// LocaleService localeService,
// ClaimExtractor claimExtractor,
// CurrentPrincipalResolver currentPrincipalResolver,
// PlatformTransactionManager transactionManager,
// UserInterceptorCacheService userInterceptorCacheService
// ) {
// this.userScope = userScope;
// this.localeService = localeService;
// this.currentPrincipalResolver = currentPrincipalResolver;
// this.claimExtractor = claimExtractor;
// this.transactionManager = transactionManager;
// this.userInterceptorCacheService = userInterceptorCacheService;
// }
//
// @Override
// public void preHandle(WebRequest request) throws InvalidApplicationException {
// UUID userId = null;
// if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) {
// String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal());
//
// UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId));
// if (cacheValue != null) {
// userId = cacheValue.getUserId();
// } else {
// userId = this.getUserIdFromDatabase(subjectId);
// if (userId == null) userId = this.createUser(subjectId);
//
// this.userInterceptorCacheService.put(new UserInterceptorCacheService.UserInterceptorCacheValue(subjectId, userId));
// }
// }
// this.userScope.setUserId(userId);
// }
//
// private UUID getUserIdFromDatabase(String subjectId) throws InvalidApplicationException {
// CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
// CriteriaQuery<Tuple> query = criteriaBuilder.createQuery(Tuple.class);
// Root<UserEntity> root = query.from(UserEntity.class);
// query.where(
// criteriaBuilder.and(
//// criteriaBuilder.equal(root.get(UserEntity._subjectId), subjectId),
// criteriaBuilder.equal(root.get(UserEntity._isActive), IsActive.Active)
// ));
//
// query.multiselect(root.get(UserEntity._id).alias(UserEntity._id));
//
// List<Tuple> results = this.entityManager.createQuery(query).getResultList();
// if (results.size() == 1) {
// Object o;
// try {
// o = results.get(0).get(UserEntity._id);
// } catch (IllegalArgumentException e) {
// return null;
// }
// if (o == null) return null;
// try {
// return UUID.class.cast(o);
// } catch (ClassCastException e) {
// return null;
// }
// }
// return null;
// }
//
// private UUID createUser(String subjectId) {
// String name = this.claimExtractor.name(this.currentPrincipalResolver.currentPrincipal());
// String familyName = this.claimExtractor.familyName(this.currentPrincipalResolver.currentPrincipal());
// if (name == null) name = subjectId;
// UserEntity user = new UserEntity();
// user.setId(UUID.randomUUID());
// user.setCreatedAt(Instant.now());
// user.setUpdatedAt(Instant.now());
// user.setName(name);
//// user.setLastName(familyName == null ? name : familyName);
// user.setIsActive(IsActive.Active);
//// user.setSubjectId(subjectId);
//// user.setCulture(this.localeService.cultureName());
//// user.setTimezone(this.localeService.timezoneName());
//// user.setLanguage(this.localeService.language());
//
// 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);
// this.entityManager.persist(user);
//
// this.entityManager.flush();
// transactionManager.commit(status);
// } catch (Exception ex) {
// if (status != null) transactionManager.rollback(status);
// throw ex;
// }
// return user.getId();
// }
//
// @Override
// public void postHandle(@NonNull WebRequest request, ModelMap model) {
// this.userScope.setUserId(null);
// }
//
// @Override
// public void afterCompletion(@NonNull WebRequest request, Exception ex) {
// }
//}

View File

@ -1,10 +1,10 @@
package gr.cite.notification.web.scope.user;
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 {
}
//package gr.cite.notification.web.scope.user;
//
//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 {
//}

View File

@ -1,77 +1,77 @@
package gr.cite.notification.web.scope.user;
import gr.cite.notification.convention.ConventionService;
import gr.cite.notification.event.UserTouchedEvent;
import gr.cite.tools.cache.CacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import java.util.HashMap;
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;
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
}
private final ConventionService conventionService;
@Autowired
public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) {
super(options);
this.conventionService = conventionService;
}
@EventListener
public void handleUserTouchedEvent(UserTouchedEvent event) {
if (!this.conventionService.isNullOrEmpty(event.getSubjectId())) this.evict(this.buildKey(event.getSubjectId()));
if (!this.conventionService.isNullOrEmpty(event.getPreviousSubjectId())) this.evict(this.buildKey(event.getPreviousSubjectId()));
}
@Override
protected Class<UserInterceptorCacheValue> valueClass() {
return UserInterceptorCacheValue.class;
}
@Override
public String keyOf(UserInterceptorCacheValue value) {
return this.buildKey(value.getSubjectId());
}
public String buildKey(String subject) {
return this.generateKey(new HashMap<>() {{
put("$subject$", subject);
}});
}
}
//package gr.cite.notification.web.scope.user;
//
//import gr.cite.notification.convention.ConventionService;
//import gr.cite.notification.event.UserTouchedEvent;
//import gr.cite.tools.cache.CacheService;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.event.EventListener;
//import org.springframework.stereotype.Service;
//
//import java.util.HashMap;
//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;
//
// public UUID getUserId() {
// return userId;
// }
//
// public void setUserId(UUID userId) {
// this.userId = userId;
// }
// }
//
// private final ConventionService conventionService;
//
// @Autowired
// public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) {
// super(options);
// this.conventionService = conventionService;
// }
//
// @EventListener
// public void handleUserTouchedEvent(UserTouchedEvent event) {
// if (!this.conventionService.isNullOrEmpty(event.getSubjectId())) this.evict(this.buildKey(event.getSubjectId()));
// if (!this.conventionService.isNullOrEmpty(event.getPreviousSubjectId())) this.evict(this.buildKey(event.getPreviousSubjectId()));
// }
//
// @Override
// protected Class<UserInterceptorCacheValue> valueClass() {
// return UserInterceptorCacheValue.class;
// }
//
// @Override
// public String keyOf(UserInterceptorCacheValue value) {
// return this.buildKey(value.getSubjectId());
// }
//
//
// public String buildKey(String subject) {
// return this.generateKey(new HashMap<>() {{
// put("$subject$", subject);
// }});
// }
//}

View File

@ -19,18 +19,12 @@ idpclient:
- type: email
Roles:
- type: resource_access
path: intelcomp-sti-viewer-dev.roles
- type: authorities
filterBy: "(.*):::TenantCode::"
extractByExpression: "(.*):(.*)"
extractExpressionValue: "[[g1]]"
path: dmp_web.roles
Scope:
- type: scope
AccessToken:
- type: x-access-token
visibility: SENSITIVE
Tenant:
- type: x-tenant
IssuedAt:
- type: iat
Issuer:
@ -43,8 +37,3 @@ idpclient:
- type: azp
Authorities:
- type: authorities
TenantCodes:
- type: authorities
filterBy: "(.*):(.*)"
extractByExpression: "(.*):(.*)"
extractExpressionValue: "[[g2]]"

View File

@ -19,18 +19,12 @@ idpclient:
- type: email
Roles:
- type: resource_access
path: intelcomp-sti-viewer-dev.roles
- type: authorities
filterBy: "(.*):::TenantCode::"
extractByExpression: "(.*):(.*)"
extractExpressionValue: "[[g1]]"
path: dmp_web.roles
Scope:
- type: scope
AccessToken:
- type: x-access-token
visibility: SENSITIVE
Tenant:
- type: x-tenant
IssuedAt:
- type: iat
Issuer:
@ -43,8 +37,3 @@ idpclient:
- type: azp
Authorities:
- type: authorities
TenantCodes:
- type: authorities
filterBy: "(.*):(.*)"
extractByExpression: "(.*):(.*)"
extractExpressionValue: "[[g2]]"

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -30,9 +30,11 @@ public class UserContactInfoQuery extends QueryBase<UserContactInfoEntity> {
private Collection<UUID> ids;
private Collection<UUID> userIds;
private Collection<UUID> excludedUserIds;
private Collection<UUID> tenantIds;
private Collection<IsActive> isActives;
private Collection<ContactInfoType> type;
private Collection<String> values;
private UserQuery userQuery;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@ -78,6 +80,21 @@ public class UserContactInfoQuery extends QueryBase<UserContactInfoEntity> {
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) {
this.tenantIds = List.of(value);
return this;
@ -123,6 +140,21 @@ public class UserContactInfoQuery extends QueryBase<UserContactInfoEntity> {
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) {
this.userQuery = subQuery;
return this;
@ -135,7 +167,8 @@ public class UserContactInfoQuery extends QueryBase<UserContactInfoEntity> {
@Override
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
@ -170,6 +203,12 @@ public class UserContactInfoQuery extends QueryBase<UserContactInfoEntity> {
for (UUID item : this.userIds) inClause.value(item);
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) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserContactInfoEntity._tenantId));
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);
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) {
Subquery<UserEntity> subQuery = queryContext.Query.subquery(this.userQuery.entityClass());
this.applySubQuery(this.userQuery, queryContext.CriteriaBuilder, subQuery);

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -83,7 +83,7 @@ public class NotificationServiceTemplateImpl implements NotificationTemplateServ
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));
// this.authorizationService.authorizeForce(Permission.EditNotificationTemplate); TODO
this.authorizationService.authorizeForce(Permission.EditNotificationTemplate);
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());