Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring
# Conflicts: # dmp-frontend/src/app/ui/description/editor/description-form/description-form-annotation.service.ts
This commit is contained in:
commit
ba26a1bd67
|
@ -0,0 +1,56 @@
|
|||
package gr.cite.annotation.web.authorization;
|
||||
|
||||
import gr.cite.annotation.authorization.AffiliatedAuthorizationRequirement;
|
||||
import gr.cite.annotation.authorization.AffiliatedResource;
|
||||
import gr.cite.commons.web.authz.handler.AuthorizationHandler;
|
||||
import gr.cite.commons.web.authz.handler.AuthorizationHandlerContext;
|
||||
import gr.cite.commons.web.authz.policy.AuthorizationRequirement;
|
||||
import gr.cite.commons.web.oidc.principal.MyPrincipal;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("affiliatedAuthorizationHandler")
|
||||
public class AffiliatedAuthorizationHandler extends AuthorizationHandler<AffiliatedAuthorizationRequirement> {
|
||||
|
||||
private final CustomPermissionAttributesConfiguration myConfiguration;
|
||||
|
||||
@Autowired
|
||||
public AffiliatedAuthorizationHandler(CustomPermissionAttributesConfiguration myConfiguration) {
|
||||
this.myConfiguration = myConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int handleRequirement(AuthorizationHandlerContext context, Object resource, AuthorizationRequirement requirement) {
|
||||
AffiliatedAuthorizationRequirement req = (AffiliatedAuthorizationRequirement) requirement;
|
||||
if (req.getRequiredPermissions() == null)
|
||||
return ACCESS_NOT_DETERMINED;
|
||||
|
||||
AffiliatedResource rs = (AffiliatedResource) resource;
|
||||
|
||||
boolean isAuthenticated = ((MyPrincipal) context.getPrincipal()).isAuthenticated();
|
||||
if (!isAuthenticated)
|
||||
return ACCESS_NOT_DETERMINED;
|
||||
|
||||
if (myConfiguration.getMyPolicies() == null)
|
||||
return ACCESS_NOT_DETERMINED;
|
||||
|
||||
int hits = 0;
|
||||
Boolean entityAffiliated = rs != null && rs.getAffiliated() != null ? rs.getAffiliated() : null;
|
||||
|
||||
for (String permission : req.getRequiredPermissions()) {
|
||||
CustomPermissionAttributesProperties.MyPermission policy = myConfiguration.getMyPolicies().get(permission);
|
||||
boolean hasPermission = policy != null && policy.getEntityAffiliated() != null && policy.getEntityAffiliated() && entityAffiliated != null && entityAffiliated;
|
||||
if (hasPermission) hits += 1;
|
||||
}
|
||||
if ((req.getMatchAll() && req.getRequiredPermissions().size() == hits) || (!req.getMatchAll() && hits > 0))
|
||||
return ACCESS_GRANTED;
|
||||
|
||||
return ACCESS_NOT_DETERMINED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends AuthorizationRequirement> supporting() {
|
||||
return AffiliatedAuthorizationRequirement.class;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package gr.cite.annotation.web.authorization;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(CustomPermissionAttributesProperties.class)
|
||||
public class CustomPermissionAttributesConfiguration {
|
||||
|
||||
private final CustomPermissionAttributesProperties properties;
|
||||
|
||||
@Autowired
|
||||
public CustomPermissionAttributesConfiguration(CustomPermissionAttributesProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public HashMap<String, CustomPermissionAttributesProperties.MyPermission> getMyPolicies() {
|
||||
return properties.getPolicies();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package gr.cite.annotation.web.authorization;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.bind.ConstructorBinding;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@ConfigurationProperties(prefix = "permissions")
|
||||
@ConditionalOnProperty(prefix = "permissions", name = "enabled", havingValue = "true")
|
||||
public class CustomPermissionAttributesProperties {
|
||||
|
||||
private final HashMap<String, MyPermission> policies;
|
||||
|
||||
@ConstructorBinding
|
||||
public CustomPermissionAttributesProperties(HashMap<String, MyPermission> policies) {
|
||||
this.policies = policies;
|
||||
}
|
||||
|
||||
public HashMap<String, MyPermission> getPolicies() {
|
||||
return policies;
|
||||
}
|
||||
|
||||
public static class MyPermission {
|
||||
|
||||
private final Boolean entityAffiliated;
|
||||
|
||||
@ConstructorBinding
|
||||
public MyPermission(Boolean entityAffiliated) {
|
||||
this.entityAffiliated = entityAffiliated;
|
||||
}
|
||||
|
||||
public Boolean getEntityAffiliated() {
|
||||
return entityAffiliated;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package gr.cite.annotation.web.config;
|
||||
|
||||
import gr.cite.annotation.authorization.AffiliatedAuthorizationRequirement;
|
||||
import gr.cite.annotation.authorization.AffiliatedResource;
|
||||
import gr.cite.annotation.web.authorization.AffiliatedAuthorizationHandler;
|
||||
import gr.cite.commons.web.authz.handler.AuthorizationHandler;
|
||||
import gr.cite.commons.web.authz.handler.PermissionClientAuthorizationHandler;
|
||||
import gr.cite.commons.web.authz.policy.AuthorizationRequirement;
|
||||
|
@ -37,16 +40,19 @@ public class SecurityConfiguration {
|
|||
private final AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver;
|
||||
private final Filter apiKeyFilter;
|
||||
private final OwnedAuthorizationHandler ownedAuthorizationHandler;
|
||||
private final AffiliatedAuthorizationHandler affiliatedAuthorizationHandler;
|
||||
|
||||
@Autowired
|
||||
public SecurityConfiguration(WebSecurityProperties webSecurityProperties,
|
||||
@Qualifier("tokenAuthenticationResolver") AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver,
|
||||
@Qualifier("apiKeyFilter") Filter apiKeyFilter,
|
||||
@Qualifier("ownedAuthorizationHandler") OwnedAuthorizationHandler ownedAuthorizationHandler) {
|
||||
@Qualifier("ownedAuthorizationHandler") OwnedAuthorizationHandler ownedAuthorizationHandler,
|
||||
@Qualifier("affiliatedAuthorizationHandler") AffiliatedAuthorizationHandler affiliatedAuthorizationHandler) {
|
||||
this.webSecurityProperties = webSecurityProperties;
|
||||
this.authenticationManagerResolver = authenticationManagerResolver;
|
||||
this.apiKeyFilter = apiKeyFilter;
|
||||
this.ownedAuthorizationHandler = ownedAuthorizationHandler;
|
||||
this.affiliatedAuthorizationHandler = affiliatedAuthorizationHandler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -78,7 +84,7 @@ public class SecurityConfiguration {
|
|||
//If not set / set to null, only the default authorization handlers will be used
|
||||
@Override
|
||||
public List<AuthorizationHandler<? extends AuthorizationRequirement>> addCustomHandlers() {
|
||||
return List.of(ownedAuthorizationHandler);
|
||||
return List.of(affiliatedAuthorizationHandler, ownedAuthorizationHandler);
|
||||
}
|
||||
|
||||
//Here you can register your custom authorization requirements (if any)
|
||||
|
@ -114,6 +120,9 @@ public class SecurityConfiguration {
|
|||
if (OwnedResource.class.equals(type)) {
|
||||
return new OwnedAuthorizationRequirement();
|
||||
}
|
||||
if (AffiliatedResource.class.equals(type)) {
|
||||
return new AffiliatedAuthorizationRequirement(matchAll, permissions);
|
||||
}
|
||||
throw new IllegalArgumentException("resource");
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@ package gr.cite.annotation.web.controllers;
|
|||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import gr.cite.annotation.audit.AuditableAction;
|
||||
import gr.cite.annotation.authorization.AuthorizationFlags;
|
||||
import gr.cite.annotation.data.AnnotationEntity;
|
||||
import gr.cite.annotation.model.Annotation;
|
||||
import gr.cite.annotation.model.builder.AnnotationBuilder;
|
||||
|
@ -71,9 +72,9 @@ public class AnnotationController {
|
|||
|
||||
this.censorFactory.censor(AnnotationCensor.class).censor(lookup.getProject(), null);
|
||||
|
||||
AnnotationQuery query = lookup.enrich(this.queryFactory);
|
||||
AnnotationQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrPermissionAssociated);
|
||||
List<AnnotationEntity> data = query.collect();
|
||||
List<Annotation> models = this.builderFactory.builder(AnnotationBuilder.class).build(lookup.getProject(), data);
|
||||
List<Annotation> models = this.builderFactory.builder(AnnotationBuilder.class).authorize(AuthorizationFlags.OwnerOrPermissionAssociated).build(lookup.getProject(), data);
|
||||
long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size();
|
||||
|
||||
this.auditService.track(AuditableAction.Annotation_Query, "lookup", lookup);
|
||||
|
@ -87,8 +88,8 @@ public class AnnotationController {
|
|||
|
||||
this.censorFactory.censor(AnnotationCensor.class).censor(fieldSet, null);
|
||||
|
||||
AnnotationQuery query = this.queryFactory.query(AnnotationQuery.class).ids(id);
|
||||
Annotation model = this.builderFactory.builder(AnnotationBuilder.class).build(fieldSet, query.firstAs(fieldSet));
|
||||
AnnotationQuery query = this.queryFactory.query(AnnotationQuery.class).authorize(AuthorizationFlags.OwnerOrPermissionAssociated).ids(id);
|
||||
Annotation model = this.builderFactory.builder(AnnotationBuilder.class).authorize(AuthorizationFlags.OwnerOrPermissionAssociated).build(fieldSet, query.firstAs(fieldSet));
|
||||
if (model == null)
|
||||
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Annotation.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ public class TenantConfigurationController {
|
|||
|
||||
TenantConfigurationQuery query = lookup.enrich(this.queryFactory);
|
||||
List<TenantConfigurationEntity> data = query.collectAs(lookup.getProject());
|
||||
List<TenantConfiguration> models = this.builderFactory.builder(TenantConfigurationBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(lookup.getProject(), data);
|
||||
List<TenantConfiguration> models = this.builderFactory.builder(TenantConfigurationBuilder.class).authorize(AuthorizationFlags.OwnerOrPermissionAssociated).build(lookup.getProject(), data);
|
||||
long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size();
|
||||
|
||||
this.auditService.track(AuditableAction.Tenant_Configuration_Query, "lookup", lookup);
|
||||
|
@ -83,7 +83,7 @@ public class TenantConfigurationController {
|
|||
this.censorFactory.censor(TenantConfigurationCensor.class).censor(fieldSet);
|
||||
|
||||
TenantConfigurationQuery query = this.queryFactory.query(TenantConfigurationQuery.class).ids(id);
|
||||
TenantConfiguration model = this.builderFactory.builder(TenantConfigurationBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.firstAs(fieldSet));
|
||||
TenantConfiguration model = this.builderFactory.builder(TenantConfigurationBuilder.class).authorize(AuthorizationFlags.OwnerOrPermissionAssociated).build(fieldSet, query.firstAs(fieldSet));
|
||||
if (model == null)
|
||||
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, TenantConfiguration.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
|
|
|
@ -32,6 +32,12 @@ cache:
|
|||
maximumSize: 500
|
||||
enableRecordStats: false
|
||||
expireAfterWriteSeconds: 320
|
||||
- names: [ "affiliation" ]
|
||||
allowNullValues: true
|
||||
initialCapacity: 100
|
||||
maximumSize: 5000
|
||||
enableRecordStats: false
|
||||
expireAfterWriteSeconds: 20
|
||||
mapCaches:
|
||||
apiKey:
|
||||
name: apikey
|
||||
|
@ -48,3 +54,6 @@ cache:
|
|||
userAllowedTenant:
|
||||
name: userAccessTenant
|
||||
keyPattern: user_access_tenant_$user_id$_$tenant_id$:v0
|
||||
affiliation:
|
||||
name: affiliation
|
||||
keyPattern: affiliation_$entity$_$user$_$type$:v0
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
permissions:
|
||||
extendedClaims: [ ]
|
||||
policies:
|
||||
|
||||
DeferredAffiliation:
|
||||
roles:
|
||||
- Admin
|
||||
- User
|
||||
- Manager
|
||||
- DescriptionTemplateEditor
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
# Tenants
|
||||
BrowseTenant:
|
||||
roles:
|
||||
|
@ -49,30 +56,18 @@ permissions:
|
|||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
# UserContactInfo
|
||||
BrowseUserContactInfo:
|
||||
roles:
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: true
|
||||
allowAuthenticated: false
|
||||
EditUserContactInfo:
|
||||
roles:
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
DeleteUserContactInfo:
|
||||
roles:
|
||||
- Admin
|
||||
claims: [ ]
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
#Annotation
|
||||
BrowseAnnotation:
|
||||
roles:
|
||||
- Admin
|
||||
entityAffiliated: true
|
||||
clients: [ ]
|
||||
allowAnonymous: true
|
||||
allowAuthenticated: false
|
||||
NewAnnotation:
|
||||
roles:
|
||||
- Admin
|
||||
entityAffiliated: true
|
||||
clients: [ ]
|
||||
allowAnonymous: true
|
||||
allowAuthenticated: false
|
||||
|
@ -85,6 +80,7 @@ permissions:
|
|||
DeleteAnnotation:
|
||||
roles:
|
||||
- Admin
|
||||
entityAffiliated: false
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
|
@ -101,5 +97,3 @@ permissions:
|
|||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
|
||||
# ViewPage Permissions
|
|
@ -45,7 +45,8 @@ queue:
|
|||
tenant-touch-topic: tenant.touch
|
||||
user-removal-topic: user.remove
|
||||
user-touch-topic: user.touch
|
||||
annotation-entity-touch-topic: annotation.entity.touch
|
||||
annotation-entities-touch-topic: annotation.entities.touch
|
||||
annotation-entities-removal-topic: annotation.entities.remove
|
||||
rabbitmq:
|
||||
enable: false
|
||||
interval-seconds: 30
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
<artifactId>oidc-authn</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>2.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
|
@ -72,7 +72,7 @@
|
|||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
<artifactId>oidc-authz</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>2.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
|
@ -82,7 +82,7 @@
|
|||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
<artifactId>validation</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<version>3.0.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package gr.cite.annotation.authorization;
|
||||
|
||||
import gr.cite.commons.web.authz.policy.AuthorizationRequirement;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class AffiliatedAuthorizationRequirement implements AuthorizationRequirement {
|
||||
private final Set<String> requiredPermissions;
|
||||
private final boolean matchAll;
|
||||
|
||||
public AffiliatedAuthorizationRequirement(Set<String> requiredPermissions) {
|
||||
this(false, requiredPermissions);
|
||||
}
|
||||
|
||||
public AffiliatedAuthorizationRequirement(String... requiredPermissions) {
|
||||
this(false, requiredPermissions);
|
||||
|
||||
}
|
||||
|
||||
public AffiliatedAuthorizationRequirement(boolean matchAll, Set<String> requiredPermissions) {
|
||||
this.matchAll = matchAll;
|
||||
this.requiredPermissions = requiredPermissions;
|
||||
}
|
||||
|
||||
public AffiliatedAuthorizationRequirement(boolean matchAll, String... requiredPermissions) {
|
||||
this.requiredPermissions = new HashSet<>();
|
||||
this.matchAll = matchAll;
|
||||
this.requiredPermissions.addAll(Arrays.stream(requiredPermissions).distinct().toList());
|
||||
}
|
||||
|
||||
public Set<String> getRequiredPermissions() {
|
||||
return requiredPermissions;
|
||||
}
|
||||
|
||||
public boolean getMatchAll() {
|
||||
return matchAll;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package gr.cite.annotation.authorization;
|
||||
|
||||
import gr.cite.commons.web.authz.policy.AuthorizationResource;
|
||||
|
||||
public class AffiliatedResource extends AuthorizationResource {
|
||||
private Boolean isAffiliated;
|
||||
|
||||
public AffiliatedResource() {
|
||||
}
|
||||
|
||||
public AffiliatedResource(Boolean isAffiliated) {
|
||||
this.isAffiliated = isAffiliated;
|
||||
}
|
||||
|
||||
public Boolean getAffiliated() {
|
||||
return isAffiliated;
|
||||
}
|
||||
|
||||
public void setAffiliated(Boolean affiliated) {
|
||||
isAffiliated = affiliated;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,6 @@ package gr.cite.annotation.authorization;
|
|||
import java.util.EnumSet;
|
||||
|
||||
public enum AuthorizationFlags {
|
||||
None, Permission, Owner;
|
||||
public static final EnumSet<AuthorizationFlags> OwnerOrPermission = EnumSet.of(Owner, Permission);
|
||||
None, Permission, Associated, Owner;
|
||||
public static final EnumSet<AuthorizationFlags> OwnerOrPermissionAssociated = EnumSet.of(Owner, Permission, Associated);
|
||||
}
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
package gr.cite.annotation.authorization;
|
||||
|
||||
public final class Permission {
|
||||
public static String DeferredAffiliation = "DeferredAffiliation";
|
||||
//User
|
||||
public static String BrowseUser = "BrowseUser";
|
||||
public static String EditUser = "EditUser";
|
||||
public static String DeleteUser = "DeleteUser";
|
||||
|
||||
//UserContactInfo
|
||||
public static String BrowseUserContactInfo = "BrowseUserContactInfo";
|
||||
public static String EditUserContactInfo = "EditUserContactInfo";
|
||||
public static String DeleteUserContactInfo = "DeleteUserContactInfo";
|
||||
|
||||
//Tenant
|
||||
public static String BrowseTenant = "BrowseTenant";
|
||||
|
@ -19,13 +16,12 @@ public final class Permission {
|
|||
|
||||
//Annotation
|
||||
public static final String BrowseAnnotation = "BrowseAnnotation";
|
||||
public static String NewAnnotation = "NewAnnotation";
|
||||
public static String EditAnnotation = "EditAnnotation";
|
||||
public static String DeleteAnnotation = "DeleteAnnotation";
|
||||
|
||||
public static final String BrowseTenantConfiguration = "BrowseTenantConfiguration";
|
||||
public static final String EditTenantConfiguration = "EditTenantConfiguration";
|
||||
|
||||
// UI Pages
|
||||
public static String ViewTenantConfigurationPage = "ViewTenantConfigurationPage";
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package gr.cite.annotation.authorization;
|
||||
|
||||
import gr.cite.annotation.convention.ConventionService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
|
||||
public class PermissionNameProvider {
|
||||
private static final Logger logger = LoggerFactory.getLogger(PermissionNameProvider.class);
|
||||
private final List<String> permissions;
|
||||
|
||||
public PermissionNameProvider(ConventionService conventionService) {
|
||||
this.permissions = new ArrayList<>();
|
||||
Class<Permission> clazz = Permission.class;
|
||||
for (Field f : clazz.getDeclaredFields()) {
|
||||
if (Modifier.isStatic(f.getModifiers())) {
|
||||
try {
|
||||
Object value = f.get(null);
|
||||
if (value != null && !conventionService.isNullOrEmpty((String)value)) this.permissions.add((String)value);
|
||||
} catch (Exception e) {
|
||||
logger.error("Can not load permission " + f.getName() + " " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package gr.cite.annotation.authorization.authorizationcontentresolver;
|
||||
|
||||
import gr.cite.tools.cache.CacheOptions;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "cache.affiliation")
|
||||
public class AffiliationCacheOptions extends CacheOptions {
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package gr.cite.annotation.authorization.authorizationcontentresolver;
|
||||
|
||||
import gr.cite.annotation.authorization.AffiliatedResource;
|
||||
import gr.cite.annotation.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.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class AffiliationCacheService extends CacheService<AffiliationCacheService.AffiliationCacheValue> {
|
||||
|
||||
public static class AffiliationCacheValue {
|
||||
|
||||
public AffiliationCacheValue() {
|
||||
}
|
||||
|
||||
public AffiliationCacheValue(UUID userId, UUID entityId, String entityType, AffiliatedResource affiliatedResource) {
|
||||
this.userId = userId;
|
||||
this.entityId = entityId;
|
||||
this.entityType = entityType;
|
||||
this.affiliatedResource = affiliatedResource;
|
||||
}
|
||||
|
||||
private UUID userId;
|
||||
private UUID entityId;
|
||||
private String entityType;
|
||||
private AffiliatedResource affiliatedResource;
|
||||
|
||||
public UUID getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(UUID userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public UUID getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public void setEntityId(UUID entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
public String getEntityType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
public void setEntityType(String entityType) {
|
||||
this.entityType = entityType;
|
||||
}
|
||||
|
||||
public AffiliatedResource getAffiliatedResource() {
|
||||
return affiliatedResource;
|
||||
}
|
||||
|
||||
public void setAffiliatedResource(AffiliatedResource affiliatedResource) {
|
||||
this.affiliatedResource = affiliatedResource;
|
||||
}
|
||||
}
|
||||
|
||||
private final ConventionService conventionService;
|
||||
@Autowired
|
||||
public AffiliationCacheService(AffiliationCacheOptions options, ConventionService conventionService) {
|
||||
super(options);
|
||||
this.conventionService = conventionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<AffiliationCacheValue> valueClass() {
|
||||
return AffiliationCacheValue.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String keyOf(AffiliationCacheValue value) {
|
||||
return this.buildKey(value.getUserId(), value.getEntityId(), value.getEntityType());
|
||||
}
|
||||
|
||||
|
||||
public String buildKey(UUID userId, UUID entityId, String entityType) {
|
||||
if (userId == null) throw new IllegalArgumentException("userId id is required");
|
||||
if (entityId == null) throw new IllegalArgumentException("entityId id is required");
|
||||
if (this.conventionService.isNullOrEmpty(entityType)) throw new IllegalArgumentException("entityType id is required");
|
||||
|
||||
HashMap<String, String> keyParts = new HashMap<>();
|
||||
keyParts.put("$user$", userId.toString().replace("-", "").toLowerCase(Locale.ROOT));
|
||||
keyParts.put("$entity$", entityId.toString().replace("-", "").toLowerCase(Locale.ROOT));
|
||||
keyParts.put("$type$", entityType);
|
||||
return this.generateKey(keyParts);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package gr.cite.annotation.authorization.authorizationcontentresolver;
|
||||
|
||||
|
||||
import gr.cite.annotation.authorization.AffiliatedResource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface AuthorizationContentResolver {
|
||||
AffiliatedResource entityAffiliation(UUID id);
|
||||
|
||||
Map<UUID, AffiliatedResource> entitiesAffiliation(List<UUID> ids);
|
||||
|
||||
List<String> getPermissionNames();
|
||||
|
||||
AffiliatedResource annotationAffiliation(UUID id);
|
||||
|
||||
Map<UUID, AffiliatedResource> annotationsAffiliation(List<UUID> ids);
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
package gr.cite.annotation.authorization.authorizationcontentresolver;
|
||||
|
||||
import gr.cite.annotation.authorization.AffiliatedResource;
|
||||
import gr.cite.annotation.authorization.PermissionNameProvider;
|
||||
import gr.cite.annotation.common.enums.IsActive;
|
||||
import gr.cite.annotation.common.scope.user.UserScope;
|
||||
import gr.cite.annotation.data.AnnotationEntity;
|
||||
import gr.cite.annotation.data.EntityUserEntity;
|
||||
import gr.cite.annotation.model.Annotation;
|
||||
import gr.cite.annotation.model.EntityUser;
|
||||
import gr.cite.annotation.query.AnnotationQuery;
|
||||
import gr.cite.annotation.query.EntityUserQuery;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.context.annotation.RequestScope;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequestScope
|
||||
public class AuthorizationContentResolverImpl implements AuthorizationContentResolver {
|
||||
private final QueryFactory queryFactory;
|
||||
private final UserScope userScope;
|
||||
private final AffiliationCacheService affiliationCacheService;
|
||||
private final PermissionNameProvider permissionNameProvider;
|
||||
public AuthorizationContentResolverImpl(QueryFactory queryFactory, UserScope userScope, AffiliationCacheService affiliationCacheService, PermissionNameProvider permissionNameProvider) {
|
||||
this.queryFactory = queryFactory;
|
||||
this.userScope = userScope;
|
||||
this.affiliationCacheService = affiliationCacheService;
|
||||
this.permissionNameProvider = permissionNameProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffiliatedResource entityAffiliation(UUID id) {
|
||||
return this.entitiesAffiliation(List.of(id)).getOrDefault(id, new AffiliatedResource());
|
||||
}
|
||||
@Override
|
||||
public Map<UUID, AffiliatedResource> entitiesAffiliation(List<UUID> ids){
|
||||
UUID userId = this.userScope.getUserIdSafe();
|
||||
Map<UUID, AffiliatedResource> affiliatedResources = new HashMap<>();
|
||||
for (UUID id : ids){
|
||||
affiliatedResources.put(id, new AffiliatedResource());
|
||||
}
|
||||
if (userId == null || !userScope.isSet()) return affiliatedResources;
|
||||
|
||||
List<UUID> idsToResolve = this.getAffiliatedFromCache(ids, userId, affiliatedResources, AnnotationEntity._entityId);
|
||||
if (idsToResolve.isEmpty()) return affiliatedResources;
|
||||
|
||||
List<EntityUserEntity> entityUsers = this.queryFactory.query(EntityUserQuery.class).entityIds(ids).userIds(userId).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(EntityUser._id).ensure(EntityUser._entityId));
|
||||
|
||||
for (UUID entityId : entityUsers.stream().map(EntityUserEntity::getEntityId).distinct().toList()){
|
||||
affiliatedResources.get(entityId).setAffiliated(true);
|
||||
}
|
||||
|
||||
this.ensureAffiliatedInCache(idsToResolve, userId, affiliatedResources, AnnotationEntity._entityId);
|
||||
return affiliatedResources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPermissionNames() {
|
||||
return permissionNameProvider.getPermissions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffiliatedResource annotationAffiliation(UUID id) {
|
||||
return this.annotationsAffiliation(List.of(id)).getOrDefault(id, new AffiliatedResource());
|
||||
}
|
||||
@Override
|
||||
public Map<UUID, AffiliatedResource> annotationsAffiliation(List<UUID> ids){
|
||||
UUID userId = this.userScope.getUserIdSafe();
|
||||
Map<UUID, AffiliatedResource> affiliatedResources = new HashMap<>();
|
||||
for (UUID id : ids){
|
||||
affiliatedResources.put(id, new AffiliatedResource());
|
||||
}
|
||||
if (userId == null || !userScope.isSet()) return affiliatedResources;
|
||||
|
||||
List<UUID> idsToResolve = this.getAffiliatedFromCache(ids, userId, affiliatedResources, AnnotationEntity.class.getSimpleName());
|
||||
if (idsToResolve.isEmpty()) return affiliatedResources;
|
||||
|
||||
List<AnnotationEntity> annotationEntities = this.queryFactory.query(AnnotationQuery.class).ids(ids).collectAs(new BaseFieldSet().ensure(Annotation._id).ensure(Annotation._entityId).ensure(Annotation._id));
|
||||
List<EntityUserEntity> entityUsers = this.queryFactory.query(EntityUserQuery.class).entityIds(annotationEntities.stream().map(AnnotationEntity::getEntityId).distinct().toList()).userIds(userId).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(EntityUser._id).ensure(EntityUser._entityId));
|
||||
Map<UUID, List<EntityUserEntity>> dmpUsersMap = entityUsers.stream().collect(Collectors.groupingBy(EntityUserEntity::getEntityId));
|
||||
|
||||
for (AnnotationEntity annotation : annotationEntities){
|
||||
List<EntityUserEntity> dmpDescriptionUsers = dmpUsersMap.getOrDefault(annotation.getEntityId(), new ArrayList<>());
|
||||
if (!dmpDescriptionUsers.isEmpty()) {
|
||||
affiliatedResources.get(annotation.getId()).setAffiliated(true);
|
||||
}
|
||||
}
|
||||
|
||||
this.ensureAffiliatedInCache(idsToResolve, userId, affiliatedResources, AnnotationEntity.class.getSimpleName());
|
||||
return affiliatedResources;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private List<UUID> getAffiliatedFromCache(List<UUID> ids, UUID userId, Map<UUID, AffiliatedResource> affiliatedResources, String entityType){
|
||||
List<UUID> idsToResolve = new ArrayList<>();
|
||||
for (UUID id : ids){
|
||||
AffiliationCacheService.AffiliationCacheValue cacheValue = this.affiliationCacheService.lookup(this.affiliationCacheService.buildKey(userId, id, entityType));
|
||||
if (cacheValue != null) affiliatedResources.put(id, cacheValue.getAffiliatedResource());
|
||||
else idsToResolve.add(id);
|
||||
}
|
||||
return idsToResolve;
|
||||
}
|
||||
|
||||
private void ensureAffiliatedInCache(List<UUID> idsToResolve, UUID userId, Map<UUID, AffiliatedResource> affiliatedResources, String entityType){
|
||||
for (UUID id : idsToResolve){
|
||||
AffiliatedResource affiliatedResource = affiliatedResources.getOrDefault(id, null);
|
||||
if (affiliatedResource != null) {
|
||||
AffiliationCacheService.AffiliationCacheValue cacheValue = new AffiliationCacheService.AffiliationCacheValue(userId, id, entityType, affiliatedResource);
|
||||
this.affiliationCacheService.put(cacheValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ package gr.cite.annotation.common.validation;
|
|||
|
||||
import gr.cite.annotation.convention.ConventionService;
|
||||
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
|
||||
import gr.cite.annotation.integrationevent.inbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEvent;
|
||||
import gr.cite.tools.validation.specification.Specification;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
|
|
|
@ -2,6 +2,7 @@ package gr.cite.annotation.data;
|
|||
|
||||
import gr.cite.annotation.common.enums.IsActive;
|
||||
import gr.cite.annotation.data.conventers.IsActiveConverter;
|
||||
import gr.cite.annotation.data.conventers.QueueInboxStatusConverter;
|
||||
import gr.cite.annotation.data.types.JsonSQLType;
|
||||
import gr.cite.queueinbox.entity.QueueInbox;
|
||||
import gr.cite.queueinbox.entity.QueueInboxStatus;
|
||||
|
@ -21,17 +22,17 @@ public class QueueInboxEntity implements QueueInbox {
|
|||
|
||||
public static final String _id = "id";
|
||||
|
||||
@Column(name = "\"queue\"", nullable = false, length = 50)
|
||||
@Column(name = "\"queue\"", nullable = false, length = 200)
|
||||
private String queue;
|
||||
|
||||
public static final String _queue = "queue";
|
||||
|
||||
@Column(name = "\"exchange\"", nullable = false, length = 50)
|
||||
@Column(name = "\"exchange\"", nullable = false, length = 200)
|
||||
private String exchange;
|
||||
|
||||
public static final String _exchange = "exchange";
|
||||
|
||||
@Column(name = "\"route\"", nullable = false, length = 50)
|
||||
@Column(name = "\"route\"", nullable = false, length = 200)
|
||||
private String route;
|
||||
|
||||
public static final String _route = "route";
|
||||
|
@ -62,11 +63,11 @@ public class QueueInboxEntity implements QueueInbox {
|
|||
|
||||
public static final String _tenantId = "tenantId";
|
||||
|
||||
@Column(name = "\"status\"", length = 50, nullable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "\"status\"", nullable = false)
|
||||
@Convert(converter = QueueInboxStatusConverter.class)
|
||||
private QueueInboxStatus status;
|
||||
public final static String _status = "status";
|
||||
|
||||
public static final String _status = "status";
|
||||
|
||||
@Column(name = "\"created_at\"", nullable = false)
|
||||
private Instant createdAt;
|
||||
|
@ -79,7 +80,7 @@ public class QueueInboxEntity implements QueueInbox {
|
|||
|
||||
public static final String _updatedAt = "updatedAt";
|
||||
|
||||
@Column(name = "\"is_active\"", length = 20, nullable = false)
|
||||
@Column(name = "\"is_active\"", nullable = false)
|
||||
@Convert(converter = IsActiveConverter.class)
|
||||
private IsActive isActive;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package gr.cite.annotation.data;
|
|||
|
||||
import gr.cite.annotation.common.enums.IsActive;
|
||||
import gr.cite.annotation.data.conventers.IsActiveConverter;
|
||||
import gr.cite.annotation.data.conventers.QueueOutboxNotifyStatusConverter;
|
||||
import gr.cite.queueoutbox.entity.QueueOutbox;
|
||||
import gr.cite.queueoutbox.entity.QueueOutboxNotifyStatus;
|
||||
import jakarta.persistence.*;
|
||||
|
@ -19,12 +20,12 @@ public class QueueOutboxEntity implements QueueOutbox {
|
|||
|
||||
public static final String _id = "id";
|
||||
|
||||
@Column(name = "\"exchange\"", nullable = false, length = 50)
|
||||
@Column(name = "\"exchange\"", nullable = false, length = 200)
|
||||
private String exchange;
|
||||
|
||||
public static final String _exchange = "exchange";
|
||||
|
||||
@Column(name = "\"route\"", length = 50)
|
||||
@Column(name = "\"route\"", length = 200)
|
||||
private String route;
|
||||
|
||||
public static final String _route = "route";
|
||||
|
@ -39,11 +40,10 @@ public class QueueOutboxEntity implements QueueOutbox {
|
|||
|
||||
public static final String _message = "message";
|
||||
|
||||
@Column(name = "\"notify_status\"", length = 20, nullable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "\"notify_status\"", nullable = false)
|
||||
@Convert(converter = QueueOutboxNotifyStatusConverter.class)
|
||||
private QueueOutboxNotifyStatus notifyStatus;
|
||||
|
||||
public static final String _notifyStatus = "notifyStatus";
|
||||
public final static String _notifyStatus = "notifyStatus";
|
||||
|
||||
@Column(name = "\"retry_count\"", nullable = false)
|
||||
private Integer retryCount;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package gr.cite.annotation.data.conventers;
|
||||
|
||||
import gr.cite.queueinbox.entity.QueueInboxStatus;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
@Converter
|
||||
public class QueueInboxStatusConverter implements AttributeConverter<QueueInboxStatus, Short> {
|
||||
@Override
|
||||
public Short convertToDatabaseColumn(QueueInboxStatus value) {
|
||||
if (value == null) throw new IllegalArgumentException("Value could not be null for: " + this.getClass().getSimpleName());
|
||||
return value.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueueInboxStatus convertToEntityAttribute(Short dbData) {
|
||||
return QueueInboxStatus.of(dbData);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package gr.cite.annotation.data.conventers;
|
||||
|
||||
import gr.cite.queueoutbox.entity.QueueOutboxNotifyStatus;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
@Converter
|
||||
public class QueueOutboxNotifyStatusConverter implements AttributeConverter<QueueOutboxNotifyStatus, Short> {
|
||||
@Override
|
||||
public Short convertToDatabaseColumn(QueueOutboxNotifyStatus value) {
|
||||
if (value == null) throw new IllegalArgumentException("Value could not be null for: " + this.getClass().getSimpleName());
|
||||
return value.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueueOutboxNotifyStatus convertToEntityAttribute(Short dbData) {
|
||||
return QueueOutboxNotifyStatus.of(dbData);
|
||||
}
|
||||
}
|
|
@ -36,7 +36,8 @@ public class AppRabbitConfigurer extends RabbitConfigurer {
|
|||
bindingItems.addAll(this.inboxProperties.getTenantTouchTopic());
|
||||
bindingItems.addAll(this.inboxProperties.getUserRemovalTopic());
|
||||
bindingItems.addAll(this.inboxProperties.getUserTouchTopic());
|
||||
bindingItems.addAll(this.inboxProperties.getAnnotationEntityTouchTopic());
|
||||
bindingItems.addAll(this.inboxProperties.getAnnotationEntitiesTouchTopic());
|
||||
bindingItems.addAll(this.inboxProperties.getAnnotationEntitiesRemovalTopic());
|
||||
|
||||
return new InboxBindings(bindingItems);
|
||||
}
|
||||
|
|
|
@ -17,21 +17,23 @@ public class InboxProperties {
|
|||
|
||||
private final List<String> userTouchTopic;
|
||||
|
||||
private final List<String> annotationEntityTouchTopic;
|
||||
private final List<String> annotationEntitiesTouchTopic;
|
||||
private final List<String> annotationEntitiesRemovalTopic;
|
||||
|
||||
public InboxProperties(
|
||||
String exchange,
|
||||
List<String> tenantRemovalTopic,
|
||||
List<String> tenantTouchTopic,
|
||||
List<String> userRemovalTopic,
|
||||
List<String> userTouchTopic,
|
||||
List<String> annotationEntityTouchTopic) {
|
||||
String exchange,
|
||||
List<String> tenantRemovalTopic,
|
||||
List<String> tenantTouchTopic,
|
||||
List<String> userRemovalTopic,
|
||||
List<String> userTouchTopic,
|
||||
List<String> annotationEntitiesTouchTopic, List<String> annotationEntitiesRemovalTopic) {
|
||||
this.exchange = exchange;
|
||||
this.tenantRemovalTopic = tenantRemovalTopic;
|
||||
this.tenantTouchTopic = tenantTouchTopic;
|
||||
this.userRemovalTopic = userRemovalTopic;
|
||||
this.userTouchTopic = userTouchTopic;
|
||||
this.annotationEntityTouchTopic = annotationEntityTouchTopic;
|
||||
this.annotationEntitiesTouchTopic = annotationEntitiesTouchTopic;
|
||||
this.annotationEntitiesRemovalTopic = annotationEntitiesRemovalTopic;
|
||||
}
|
||||
|
||||
public List<String> getTenantRemovalTopic() {
|
||||
|
@ -50,8 +52,12 @@ public class InboxProperties {
|
|||
return userTouchTopic;
|
||||
}
|
||||
|
||||
public List<String> getAnnotationEntityTouchTopic() {
|
||||
return annotationEntityTouchTopic;
|
||||
public List<String> getAnnotationEntitiesTouchTopic() {
|
||||
return annotationEntitiesTouchTopic;
|
||||
}
|
||||
|
||||
public List<String> getAnnotationEntitiesRemovalTopic() {
|
||||
return annotationEntitiesRemovalTopic;
|
||||
}
|
||||
|
||||
public String getExchange() {
|
||||
|
|
|
@ -5,7 +5,8 @@ import gr.cite.annotation.common.enums.IsActive;
|
|||
import gr.cite.annotation.common.scope.fake.FakeRequestScope;
|
||||
import gr.cite.annotation.data.QueueInboxEntity;
|
||||
import gr.cite.annotation.integrationevent.TrackedEvent;
|
||||
import gr.cite.annotation.integrationevent.inbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
|
||||
import gr.cite.annotation.integrationevent.inbox.annotationentitiesremoval.AnnotationEntitiesRemovalIntegrationEventHandler;
|
||||
import gr.cite.annotation.integrationevent.inbox.annotationentitiestouch.AnnotationEntitiesTouchedIntegrationEventHandler;
|
||||
import gr.cite.annotation.integrationevent.inbox.tenantremoval.TenantRemovalIntegrationEventHandler;
|
||||
import gr.cite.annotation.integrationevent.inbox.tenanttouch.TenantTouchedIntegrationEventHandler;
|
||||
import gr.cite.annotation.integrationevent.inbox.userremoval.UserRemovalIntegrationEventHandler;
|
||||
|
@ -332,8 +333,10 @@ public class InboxRepositoryImpl implements InboxRepository {
|
|||
handler = this.applicationContext.getBean(UserRemovalIntegrationEventHandler.class);
|
||||
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getUserTouchTopic()))
|
||||
handler = this.applicationContext.getBean(UserTouchedIntegrationEventHandler.class);
|
||||
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getAnnotationEntityTouchTopic()))
|
||||
handler = this.applicationContext.getBean(AnnotationEntityTouchedIntegrationEventHandler.class);
|
||||
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getAnnotationEntitiesTouchTopic()))
|
||||
handler = this.applicationContext.getBean(AnnotationEntitiesTouchedIntegrationEventHandler.class);
|
||||
else if (this.routingKeyMatched(routingKey, this.inboxProperties.getAnnotationEntitiesRemovalTopic()))
|
||||
handler = this.applicationContext.getBean(AnnotationEntitiesRemovalIntegrationEventHandler.class);
|
||||
else {
|
||||
logger.error("No handler found for message routing key '{}'. Discarding.", routingKey);
|
||||
handler = null;
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package gr.cite.annotation.integrationevent.inbox.annotationentitiesremoval;
|
||||
|
||||
import gr.cite.annotation.common.validation.BaseValidator;
|
||||
import gr.cite.annotation.common.validation.UuidValidator;
|
||||
import gr.cite.annotation.convention.ConventionService;
|
||||
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
|
||||
import gr.cite.annotation.integrationevent.TrackedEvent;
|
||||
import gr.cite.tools.validation.ValidatorFactory;
|
||||
import gr.cite.tools.validation.specification.Specification;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AnnotationEntitiesRemovalIntegrationEvent extends TrackedEvent {
|
||||
|
||||
private List<UUID> entityIds;
|
||||
|
||||
public static final String _entityIds = "entityIds";
|
||||
|
||||
public List<UUID> getEntityIds() {
|
||||
return entityIds;
|
||||
}
|
||||
|
||||
public void setEntityIds(List<UUID> entityIds) {
|
||||
this.entityIds = entityIds;
|
||||
}
|
||||
|
||||
@Component(AnnotationEntitiesRemovalIntegrationEventValidator.ValidatorName)
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public static class AnnotationEntitiesRemovalIntegrationEventValidator extends BaseValidator<AnnotationEntitiesRemovalIntegrationEvent> {
|
||||
|
||||
public static final String ValidatorName = "AnnotationEntitiesRemovalIntegrationEventValidator";
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
private final ValidatorFactory validatorFactory;
|
||||
|
||||
protected AnnotationEntitiesRemovalIntegrationEventValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, ValidatorFactory validatorFactory) {
|
||||
super(conventionService, errors);
|
||||
this.messageSource = messageSource;
|
||||
this.validatorFactory = validatorFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<AnnotationEntitiesRemovalIntegrationEvent> modelClass() {
|
||||
return AnnotationEntitiesRemovalIntegrationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Specification> specifications(AnnotationEntitiesRemovalIntegrationEvent item) {
|
||||
return Arrays.asList(
|
||||
this.spec()
|
||||
.must(() -> !this.isListNullOrEmpty(item.getEntityIds()))
|
||||
.failOn(AnnotationEntitiesRemovalIntegrationEvent._entityIds).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntitiesRemovalIntegrationEvent._entityIds}, LocaleContextHolder.getLocale())),
|
||||
this.navSpec()
|
||||
.iff(() -> !this.isListNullOrEmpty(item.getEntityIds()))
|
||||
.on(AnnotationEntitiesRemovalIntegrationEvent._entityIds)
|
||||
.over(item.getEntityIds())
|
||||
.using((i) -> this.validatorFactory.validator(UuidValidator.class))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package gr.cite.annotation.integrationevent.inbox.annotationentitiesremoval;
|
||||
|
||||
import gr.cite.annotation.integrationevent.inbox.IntegrationEventHandler;
|
||||
|
||||
public interface AnnotationEntitiesRemovalIntegrationEventHandler extends IntegrationEventHandler {
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package gr.cite.annotation.integrationevent.inbox.annotationentitytouch;
|
||||
package gr.cite.annotation.integrationevent.inbox.annotationentitiesremoval;
|
||||
|
||||
import gr.cite.annotation.audit.AuditableAction;
|
||||
import gr.cite.annotation.common.JsonHandlingService;
|
||||
|
@ -11,6 +11,7 @@ import gr.cite.annotation.integrationevent.inbox.IntegrationEventProperties;
|
|||
import gr.cite.annotation.query.EntityUserQuery;
|
||||
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
||||
import gr.cite.tools.auditing.AuditService;
|
||||
import gr.cite.tools.data.deleter.DeleterFactory;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import gr.cite.tools.validation.ValidatorFactory;
|
||||
|
@ -24,17 +25,13 @@ import org.springframework.context.ApplicationContext;
|
|||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class AnnotationEntityTouchedIntegrationEventHandlerImpl implements AnnotationEntityTouchedIntegrationEventHandler {
|
||||
public class AnnotationEntitiesRemovalIntegrationEventHandlerImpl implements AnnotationEntitiesRemovalIntegrationEventHandler {
|
||||
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(AnnotationEntityTouchedIntegrationEventHandlerImpl.class));
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(AnnotationEntitiesRemovalIntegrationEventHandlerImpl.class));
|
||||
|
||||
private final JsonHandlingService jsonHandlingService;
|
||||
|
||||
|
@ -44,7 +41,7 @@ public class AnnotationEntityTouchedIntegrationEventHandlerImpl implements Annot
|
|||
|
||||
private final QueryFactory queryFactory;
|
||||
|
||||
public AnnotationEntityTouchedIntegrationEventHandlerImpl(JsonHandlingService jsonHandlingService, ValidatorFactory validatorFactory, ApplicationContext applicationContext, QueryFactory queryFactory) {
|
||||
public AnnotationEntitiesRemovalIntegrationEventHandlerImpl(JsonHandlingService jsonHandlingService, ValidatorFactory validatorFactory, ApplicationContext applicationContext, QueryFactory queryFactory) {
|
||||
this.jsonHandlingService = jsonHandlingService;
|
||||
this.validatorFactory = validatorFactory;
|
||||
this.applicationContext = applicationContext;
|
||||
|
@ -53,66 +50,41 @@ public class AnnotationEntityTouchedIntegrationEventHandlerImpl implements Annot
|
|||
|
||||
@Override
|
||||
public EventProcessingStatus handle(IntegrationEventProperties properties, String message) {
|
||||
AnnotationEntityTouchedIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(AnnotationEntityTouchedIntegrationEvent.class, message);
|
||||
AnnotationEntitiesRemovalIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(AnnotationEntitiesRemovalIntegrationEvent.class, message);
|
||||
if (event == null)
|
||||
return EventProcessingStatus.Error;
|
||||
|
||||
logger.debug("Handling {}", AnnotationEntityTouchedIntegrationEvent.class.getSimpleName());
|
||||
logger.debug("Handling {}", AnnotationEntitiesRemovalIntegrationEvent.class.getSimpleName());
|
||||
|
||||
this.validatorFactory.validator(AnnotationEntityTouchedIntegrationEvent.AnnotationEntityTouchedIntegrationEventValidator.class).validateForce(event);
|
||||
this.validatorFactory.validator(AnnotationEntitiesRemovalIntegrationEvent.AnnotationEntitiesRemovalIntegrationEventValidator.class).validateForce(event);
|
||||
|
||||
EntityManager entityManager = null;
|
||||
EntityTransaction transaction = null;
|
||||
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||
try {
|
||||
// QueryFactory queryFactory = this.applicationContext.getBean(QueryFactory.class);
|
||||
// TenantScope scope = this.applicationContext.getBean(TenantScope.class);
|
||||
// if (scope.isMultitenant() && event.getTenant() != null) {
|
||||
// TenantEntity tenant = queryFactory.query(TenantQuery.class).ids(event.getTenant()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code));
|
||||
// if (tenant == null) {
|
||||
// logger.error("missing tenant from event message");
|
||||
// return EventProcessingStatus.Error;
|
||||
// }
|
||||
// scope.setTenant(event.getTenant(), tenant.getCode());
|
||||
// } else if (scope.isMultitenant()) {
|
||||
// logger.error("missing tenant from event message");
|
||||
// return EventProcessingStatus.Error;
|
||||
// }
|
||||
//
|
||||
// ValidationService validator = this.applicationContext.getBean(ValidationService.class);
|
||||
// validator.validateForce(model);
|
||||
|
||||
CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class);
|
||||
currentPrincipalResolver.push(InboxPrincipal.build(properties));
|
||||
|
||||
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||
entityManager = entityManagerFactory.createEntityManager();
|
||||
|
||||
DeleterFactory deleterFactory = this.applicationContext.getBean(DeleterFactory.class);
|
||||
|
||||
transaction = entityManager.getTransaction();
|
||||
transaction.begin();
|
||||
|
||||
try {
|
||||
|
||||
EntityUserQuery entityUserQuery = this.queryFactory.query(EntityUserQuery.class);
|
||||
List<EntityUserEntity> associatedUsersEntities = entityUserQuery
|
||||
.entityIds(event.getEntityId())
|
||||
List<EntityUserEntity> items = entityUserQuery
|
||||
.entityIds(event.getEntityIds())
|
||||
.isActive(IsActive.Active)
|
||||
.collect();
|
||||
List<UUID> associatedUsers = associatedUsersEntities.stream()
|
||||
.map(EntityUserEntity::getUserId)
|
||||
.toList();
|
||||
for (UUID user : event.getUserIds()) {
|
||||
if (!associatedUsers.contains(user)) {
|
||||
EntityUserEntity entityUserEntity = new EntityUserEntity();
|
||||
entityUserEntity.setId(UUID.randomUUID());
|
||||
entityUserEntity.setEntityId(event.getEntityId());
|
||||
entityUserEntity.setUserId(user);
|
||||
entityUserEntity.setCreatedAt(Instant.now());
|
||||
entityUserEntity.setUpdatedAt(Instant.now());
|
||||
entityUserEntity.setIsActive(IsActive.Active);
|
||||
|
||||
entityManager.persist(entityUserEntity);
|
||||
}
|
||||
}
|
||||
|
||||
deleterFactory.deleter(gr.cite.EntityUser.model.deleter.EntityUserDeleter.class).delete(items);
|
||||
|
||||
entityManager.flush();
|
||||
|
||||
AuditService auditService = this.applicationContext.getBean(AuditService.class);
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
package gr.cite.annotation.integrationevent.inbox.annotationentitiestouch;
|
||||
|
||||
import gr.cite.annotation.common.validation.BaseValidator;
|
||||
import gr.cite.annotation.common.validation.UuidValidator;
|
||||
import gr.cite.annotation.convention.ConventionService;
|
||||
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
|
||||
import gr.cite.annotation.integrationevent.TrackedEvent;
|
||||
import gr.cite.tools.validation.ValidatorFactory;
|
||||
import gr.cite.tools.validation.specification.Specification;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AnnotationEntitiesTouchedIntegrationEvent extends TrackedEvent {
|
||||
|
||||
private List<AnnotationEntityTouchedIntegrationEvent> events;
|
||||
|
||||
public static final String _events = "events";
|
||||
|
||||
public List<AnnotationEntityTouchedIntegrationEvent> getEvents() {
|
||||
return events;
|
||||
}
|
||||
|
||||
public void setEvents(List<AnnotationEntityTouchedIntegrationEvent> events) {
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
@Component(AnnotationEntitiesTouchedIntegrationEventValidator.ValidatorName)
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public static class AnnotationEntitiesTouchedIntegrationEventValidator extends BaseValidator<AnnotationEntitiesTouchedIntegrationEvent> {
|
||||
|
||||
public static final String ValidatorName = "AnnotationEntitiesTouchedIntegrationEventValidator";
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
private final ValidatorFactory validatorFactory;
|
||||
|
||||
protected AnnotationEntitiesTouchedIntegrationEventValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, ValidatorFactory validatorFactory) {
|
||||
super(conventionService, errors);
|
||||
this.messageSource = messageSource;
|
||||
this.validatorFactory = validatorFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<AnnotationEntitiesTouchedIntegrationEvent> modelClass() {
|
||||
return AnnotationEntitiesTouchedIntegrationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Specification> specifications(AnnotationEntitiesTouchedIntegrationEvent item) {
|
||||
return Arrays.asList(
|
||||
this.spec()
|
||||
.must(() -> !this.isListNullOrEmpty(item.getEvents()))
|
||||
.failOn(AnnotationEntitiesTouchedIntegrationEvent._events).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntitiesTouchedIntegrationEvent._events}, LocaleContextHolder.getLocale())),
|
||||
this.navSpec()
|
||||
.iff(() -> !this.isListNullOrEmpty(item.getEvents()))
|
||||
.on(AnnotationEntitiesTouchedIntegrationEvent._events)
|
||||
.over(item.getEvents())
|
||||
.using((i) -> this.validatorFactory.validator(AnnotationEntityTouchedIntegrationEvent.AnnotationEntityTouchedIntegrationEventValidator.class))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AnnotationEntityTouchedIntegrationEvent {
|
||||
|
||||
private UUID entityId;
|
||||
|
||||
public static final String _entityId = "entityId";
|
||||
|
||||
private List<UUID> userIds;
|
||||
|
||||
public static final String _userIds = "userIds";
|
||||
|
||||
public UUID getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public void setEntityId(UUID entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
public List<UUID> getUserIds() {
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public void setUserIds(List<UUID> userIds) {
|
||||
this.userIds = userIds;
|
||||
}
|
||||
|
||||
@Component(AnnotationEntityTouchedIntegrationEvent.AnnotationEntityTouchedIntegrationEventValidator.ValidatorName)
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public static class AnnotationEntityTouchedIntegrationEventValidator extends BaseValidator<AnnotationEntityTouchedIntegrationEvent> {
|
||||
|
||||
public static final String ValidatorName = "AnnotationEntityTouchedIntegrationEventValidator";
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
private final ValidatorFactory validatorFactory;
|
||||
|
||||
protected AnnotationEntityTouchedIntegrationEventValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, ValidatorFactory validatorFactory) {
|
||||
super(conventionService, errors);
|
||||
this.messageSource = messageSource;
|
||||
this.validatorFactory = validatorFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<AnnotationEntityTouchedIntegrationEvent> modelClass() {
|
||||
return AnnotationEntityTouchedIntegrationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Specification> specifications(AnnotationEntityTouchedIntegrationEvent item) {
|
||||
return Arrays.asList(
|
||||
this.spec()
|
||||
.iff(() -> !this.isNull(item.getEntityId()))
|
||||
.must(() -> this.isValidGuid(item.getEntityId()))
|
||||
.failOn(AnnotationEntityTouchedIntegrationEvent._entityId).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityTouchedIntegrationEvent._entityId}, LocaleContextHolder.getLocale())),
|
||||
this.spec()
|
||||
.must(() -> !this.isListNullOrEmpty(item.getUserIds()))
|
||||
.failOn(AnnotationEntityTouchedIntegrationEvent._userIds).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityTouchedIntegrationEvent._userIds}, LocaleContextHolder.getLocale())),
|
||||
this.navSpec()
|
||||
.iff(() -> !this.isListNullOrEmpty(item.getUserIds()))
|
||||
.on(AnnotationEntityTouchedIntegrationEvent._userIds)
|
||||
.over(item.getUserIds())
|
||||
.using((i) -> this.validatorFactory.validator(UuidValidator.class))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package gr.cite.annotation.integrationevent.inbox.annotationentitytouch;
|
||||
package gr.cite.annotation.integrationevent.inbox.annotationentitiestouch;
|
||||
|
||||
import gr.cite.annotation.integrationevent.inbox.IntegrationEventHandler;
|
||||
|
||||
public interface AnnotationEntityTouchedIntegrationEventHandler extends IntegrationEventHandler {
|
||||
public interface AnnotationEntitiesTouchedIntegrationEventHandler extends IntegrationEventHandler {
|
||||
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
package gr.cite.annotation.integrationevent.inbox.annotationentitiestouch;
|
||||
|
||||
import gr.cite.annotation.audit.AuditableAction;
|
||||
import gr.cite.annotation.common.JsonHandlingService;
|
||||
import gr.cite.annotation.common.enums.IsActive;
|
||||
import gr.cite.annotation.common.scope.fake.FakeRequestScope;
|
||||
import gr.cite.annotation.data.EntityUserEntity;
|
||||
import gr.cite.annotation.integrationevent.inbox.EventProcessingStatus;
|
||||
import gr.cite.annotation.integrationevent.inbox.InboxPrincipal;
|
||||
import gr.cite.annotation.integrationevent.inbox.IntegrationEventProperties;
|
||||
import gr.cite.annotation.query.EntityUserQuery;
|
||||
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
||||
import gr.cite.tools.auditing.AuditService;
|
||||
import gr.cite.tools.data.deleter.DeleterFactory;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import gr.cite.tools.validation.ValidatorFactory;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import jakarta.persistence.EntityTransaction;
|
||||
import jakarta.persistence.OptimisticLockException;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class AnnotationEntitiesTouchedIntegrationEventHandlerImpl implements AnnotationEntitiesTouchedIntegrationEventHandler {
|
||||
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(AnnotationEntitiesTouchedIntegrationEventHandlerImpl.class));
|
||||
|
||||
private final JsonHandlingService jsonHandlingService;
|
||||
|
||||
private final ValidatorFactory validatorFactory;
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
private final QueryFactory queryFactory;
|
||||
|
||||
public AnnotationEntitiesTouchedIntegrationEventHandlerImpl(JsonHandlingService jsonHandlingService, ValidatorFactory validatorFactory, ApplicationContext applicationContext, QueryFactory queryFactory) {
|
||||
this.jsonHandlingService = jsonHandlingService;
|
||||
this.validatorFactory = validatorFactory;
|
||||
this.applicationContext = applicationContext;
|
||||
this.queryFactory = queryFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventProcessingStatus handle(IntegrationEventProperties properties, String message) {
|
||||
AnnotationEntitiesTouchedIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(AnnotationEntitiesTouchedIntegrationEvent.class, message);
|
||||
if (event == null)
|
||||
return EventProcessingStatus.Error;
|
||||
|
||||
logger.debug("Handling {}", AnnotationEntitiesTouchedIntegrationEvent.class.getSimpleName());
|
||||
|
||||
this.validatorFactory.validator(AnnotationEntitiesTouchedIntegrationEvent.AnnotationEntitiesTouchedIntegrationEventValidator.class).validateForce(event);
|
||||
|
||||
EntityManager entityManager = null;
|
||||
EntityTransaction transaction = null;
|
||||
try (FakeRequestScope ignored = new FakeRequestScope()) {
|
||||
try {
|
||||
CurrentPrincipalResolver currentPrincipalResolver = this.applicationContext.getBean(CurrentPrincipalResolver.class);
|
||||
currentPrincipalResolver.push(InboxPrincipal.build(properties));
|
||||
|
||||
EntityManagerFactory entityManagerFactory = this.applicationContext.getBean(EntityManagerFactory.class);
|
||||
entityManager = entityManagerFactory.createEntityManager();
|
||||
|
||||
DeleterFactory deleterFactory = this.applicationContext.getBean(DeleterFactory.class);
|
||||
|
||||
transaction = entityManager.getTransaction();
|
||||
transaction.begin();
|
||||
|
||||
try {
|
||||
for (AnnotationEntitiesTouchedIntegrationEvent.AnnotationEntityTouchedIntegrationEvent entityEvent : event.getEvents()) {
|
||||
|
||||
EntityUserQuery entityUserQuery = this.queryFactory.query(EntityUserQuery.class);
|
||||
List<EntityUserEntity> items = entityUserQuery
|
||||
.entityIds(entityEvent.getEntityId())
|
||||
.isActive(IsActive.Active)
|
||||
.collect();
|
||||
List<UUID> updatedCreatedIds = new ArrayList<>();
|
||||
for (UUID user : entityEvent.getUserIds()) {
|
||||
EntityUserEntity data = items.stream().filter(x -> x.getUserId().equals(user)).findFirst().orElse(null);
|
||||
if (data == null) {
|
||||
data = new EntityUserEntity();
|
||||
data.setId(UUID.randomUUID());
|
||||
data.setEntityId(entityEvent.getEntityId());
|
||||
data.setUserId(user);
|
||||
data.setCreatedAt(Instant.now());
|
||||
data.setUpdatedAt(Instant.now());
|
||||
data.setIsActive(IsActive.Active);
|
||||
|
||||
entityManager.persist(data);
|
||||
}
|
||||
updatedCreatedIds.add(data.getId());
|
||||
}
|
||||
|
||||
List<EntityUserEntity> toDelete = items.stream().filter(x -> updatedCreatedIds.stream().noneMatch(y -> y.equals(x.getId()))).collect(Collectors.toList());
|
||||
deleterFactory.deleter(gr.cite.EntityUser.model.deleter.EntityUserDeleter.class).delete(toDelete);
|
||||
|
||||
entityManager.flush();
|
||||
}
|
||||
|
||||
AuditService auditService = this.applicationContext.getBean(AuditService.class);
|
||||
|
||||
auditService.track(AuditableAction.User_Persist, Map.ofEntries(
|
||||
new AbstractMap.SimpleEntry<String, Object>("model", event)
|
||||
));
|
||||
|
||||
transaction.commit();
|
||||
} catch (Exception e) {
|
||||
transaction.rollback();
|
||||
throw e;
|
||||
} finally {
|
||||
currentPrincipalResolver.pop();
|
||||
}
|
||||
} catch (OptimisticLockException ex) {
|
||||
// we get this if/when someone else already modified the notifications. We want to essentially ignore this, and keep working
|
||||
logger.debug("Concurrency exception getting queue outbox. Skipping: {} ", ex.getMessage());
|
||||
if (transaction != null)
|
||||
transaction.rollback();
|
||||
} catch (Exception ex) {
|
||||
logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
|
||||
if (transaction != null)
|
||||
transaction.rollback();
|
||||
} finally {
|
||||
if (entityManager != null)
|
||||
entityManager.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error("Problem getting list of queue outbox. Skipping: {}", ex.getMessage(), ex);
|
||||
}
|
||||
return EventProcessingStatus.Success;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
package gr.cite.annotation.integrationevent.inbox.annotationentitytouch;
|
||||
|
||||
import gr.cite.annotation.common.validation.BaseValidator;
|
||||
import gr.cite.annotation.common.validation.UuidValidator;
|
||||
import gr.cite.annotation.convention.ConventionService;
|
||||
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
|
||||
import gr.cite.annotation.integrationevent.TrackedEvent;
|
||||
import gr.cite.tools.validation.ValidatorFactory;
|
||||
import gr.cite.tools.validation.specification.Specification;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AnnotationEntityTouchedIntegrationEvent extends TrackedEvent {
|
||||
|
||||
private UUID entityId;
|
||||
|
||||
public static final String _entityId = "entityId";
|
||||
|
||||
private List<UUID> userIds;
|
||||
|
||||
public static final String _userIds = "userIds";
|
||||
|
||||
public UUID getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public void setEntityId(UUID entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
public List<UUID> getUserIds() {
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public void setUserIds(List<UUID> userIds) {
|
||||
this.userIds = userIds;
|
||||
}
|
||||
|
||||
@Component(AnnotationEntityTouchedIntegrationEvent.AnnotationEntityTouchedIntegrationEventValidator.ValidatorName)
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public static class AnnotationEntityTouchedIntegrationEventValidator extends BaseValidator<AnnotationEntityTouchedIntegrationEvent> {
|
||||
|
||||
public static final String ValidatorName = "AnnotationEntityTouchedIntegrationEventValidator";
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
private final ValidatorFactory validatorFactory;
|
||||
|
||||
protected AnnotationEntityTouchedIntegrationEventValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, ValidatorFactory validatorFactory) {
|
||||
super(conventionService, errors);
|
||||
this.messageSource = messageSource;
|
||||
this.validatorFactory = validatorFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<AnnotationEntityTouchedIntegrationEvent> modelClass() {
|
||||
return AnnotationEntityTouchedIntegrationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Specification> specifications(AnnotationEntityTouchedIntegrationEvent item) {
|
||||
return Arrays.asList(
|
||||
this.spec()
|
||||
.iff(() -> !this.isNull(item.getEntityId()))
|
||||
.must(() -> this.isValidGuid(item.getEntityId()))
|
||||
.failOn(AnnotationEntityTouchedIntegrationEvent._entityId).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityTouchedIntegrationEvent._entityId}, LocaleContextHolder.getLocale())),
|
||||
this.spec()
|
||||
.must(() -> !this.isListNullOrEmpty(item.getUserIds()))
|
||||
.failOn(AnnotationEntityTouchedIntegrationEvent._userIds).failWith(messageSource.getMessage("Validation_Required", new Object[]{AnnotationEntityTouchedIntegrationEvent._userIds}, LocaleContextHolder.getLocale())),
|
||||
this.navSpec()
|
||||
.iff(() -> !this.isListNullOrEmpty(item.getUserIds()))
|
||||
.on(AnnotationEntityTouchedIntegrationEvent._userIds)
|
||||
.over(item.getUserIds())
|
||||
.using((i) -> this.validatorFactory.validator(UuidValidator.class))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -7,6 +7,7 @@ import jakarta.persistence.Column;
|
|||
import jakarta.persistence.Convert;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Annotation {
|
||||
|
@ -67,6 +68,13 @@ public class Annotation {
|
|||
|
||||
public static final String _isActive = "isActive";
|
||||
|
||||
private String hash;
|
||||
|
||||
public static final String _hash = "hash";
|
||||
|
||||
private List<String> authorizationFlags;
|
||||
public static final String _authorizationFlags = "authorizationFlags";
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -179,4 +187,19 @@ public class Annotation {
|
|||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void setHash(String hash) {
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
public List<String> getAuthorizationFlags() {
|
||||
return authorizationFlags;
|
||||
}
|
||||
|
||||
public void setAuthorizationFlags(List<String> authorizationFlags) {
|
||||
this.authorizationFlags = authorizationFlags;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package gr.cite.annotation.model;
|
||||
|
||||
import gr.cite.annotation.common.enums.AnnotationProtectionType;
|
||||
import gr.cite.annotation.common.enums.IsActive;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
public class EntityUser {
|
||||
|
||||
private UUID id;
|
||||
|
||||
public static final String _id = "id";
|
||||
|
||||
private UUID entityId;
|
||||
|
||||
public static final String _entityId = "entityId";
|
||||
|
||||
private User user;
|
||||
|
||||
public static final String _user = "user";
|
||||
|
||||
private Instant createdAt;
|
||||
|
||||
public static final String _createdAt = "createdAt";
|
||||
|
||||
private Instant updatedAt;
|
||||
|
||||
public static final String _updatedAt = "updatedAt";
|
||||
|
||||
private IsActive isActive;
|
||||
|
||||
public static final String _isActive = "isActive";
|
||||
|
||||
private String hash;
|
||||
|
||||
public static final String _hash = "hash";
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public UUID getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public void setEntityId(UUID entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public Instant getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(Instant updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public IsActive getIsActive() {
|
||||
return isActive;
|
||||
}
|
||||
|
||||
public void setIsActive(IsActive isActive) {
|
||||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void setHash(String hash) {
|
||||
this.hash = hash;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,15 @@
|
|||
package gr.cite.annotation.model.builder;
|
||||
|
||||
import gr.cite.annotation.authorization.AffiliatedResource;
|
||||
import gr.cite.annotation.authorization.AuthorizationFlags;
|
||||
import gr.cite.annotation.authorization.authorizationcontentresolver.AuthorizationContentResolver;
|
||||
import gr.cite.annotation.convention.ConventionService;
|
||||
import gr.cite.annotation.data.AnnotationEntity;
|
||||
import gr.cite.annotation.model.Annotation;
|
||||
import gr.cite.annotation.model.AnnotationAuthor;
|
||||
import gr.cite.annotation.model.User;
|
||||
import gr.cite.annotation.query.UserQuery;
|
||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||
import gr.cite.tools.data.builder.BuilderFactory;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.exception.MyApplicationException;
|
||||
|
@ -29,13 +32,17 @@ public class AnnotationBuilder extends BaseBuilder<Annotation, AnnotationEntity>
|
|||
private final QueryFactory queryFactory;
|
||||
|
||||
private final BuilderFactory builderFactory;
|
||||
private final AuthorizationContentResolver authorizationContentResolver;
|
||||
private final AuthorizationService authorizationService;
|
||||
|
||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||
|
||||
public AnnotationBuilder(ConventionService conventionService, QueryFactory queryFactory, BuilderFactory builderFactory) {
|
||||
public AnnotationBuilder(ConventionService conventionService, QueryFactory queryFactory, BuilderFactory builderFactory, AuthorizationContentResolver authorizationContentResolver, AuthorizationService authorizationService) {
|
||||
super(conventionService, new LoggerService(LoggerFactory.getLogger(AnnotationBuilder.class)));
|
||||
this.queryFactory = queryFactory;
|
||||
this.builderFactory = builderFactory;
|
||||
this.authorizationContentResolver = authorizationContentResolver;
|
||||
this.authorizationService = authorizationService;
|
||||
}
|
||||
|
||||
public AnnotationBuilder authorize(EnumSet<AuthorizationFlags> values) {
|
||||
|
@ -51,42 +58,32 @@ public class AnnotationBuilder extends BaseBuilder<Annotation, AnnotationEntity>
|
|||
return new ArrayList<>();
|
||||
|
||||
List<Annotation> models = new ArrayList<>();
|
||||
if (data == null) return models;
|
||||
|
||||
FieldSet authorFields = fields.extractPrefixed(this.asPrefix(Annotation._author));
|
||||
Map<UUID, AnnotationAuthor> authorsMap = this.collectAuthors(authorFields, data);
|
||||
Set<String> authorizationFlags = this.extractAuthorizationFlags(fields, Annotation._authorizationFlags, this.authorizationContentResolver.getPermissionNames());
|
||||
Map<UUID, AffiliatedResource> affiliatedResourceMap = authorizationFlags == null || authorizationFlags.isEmpty() ? null : this.authorizationContentResolver.annotationsAffiliation(data.stream().map(AnnotationEntity::getId).toList());
|
||||
|
||||
|
||||
if (data == null)
|
||||
return models;
|
||||
for (AnnotationEntity d : data) {
|
||||
Annotation m = new Annotation();
|
||||
if (fields.hasField(this.asIndexer(Annotation._id)))
|
||||
m.setId(d.getId());
|
||||
if (fields.hasField(this.asIndexer(Annotation._entityId)))
|
||||
m.setEntityId(d.getEntityId());
|
||||
if (fields.hasField(this.asIndexer(Annotation._entityType)))
|
||||
m.setEntityType(d.getEntityType());
|
||||
if (fields.hasField(this.asIndexer(Annotation._anchor)))
|
||||
m.setAnchor(d.getAnchor());
|
||||
if (fields.hasField(this.asIndexer(Annotation._payload)))
|
||||
m.setPayload(d.getPayload());
|
||||
if (fields.hasField(this.asIndexer(Annotation._subjectId)))
|
||||
m.setSubjectId(d.getSubjectId());
|
||||
if (authorsMap != null && authorsMap.containsKey(d.getSubjectId()))
|
||||
m.setAuthor(authorsMap.get(d.getSubjectId()));
|
||||
if (fields.hasField(this.asIndexer(Annotation._threadId)))
|
||||
m.setThreadId(d.getThreadId());
|
||||
if (fields.hasField(this.asIndexer(Annotation._parentId)))
|
||||
m.setParentId(d.getParentId());
|
||||
if (fields.hasField(this.asIndexer(Annotation._protectionType)))
|
||||
m.setProtectionType(d.getProtectionType());
|
||||
if (fields.hasField(this.asIndexer(Annotation._timeStamp)))
|
||||
m.setTimeStamp(d.getTimeStamp());
|
||||
if (fields.hasField(this.asIndexer(Annotation._createdAt)))
|
||||
m.setCreatedAt(d.getCreatedAt());
|
||||
if (fields.hasField(this.asIndexer(Annotation._updatedAt)))
|
||||
m.setUpdatedAt(d.getUpdatedAt());
|
||||
if (fields.hasField(this.asIndexer(Annotation._isActive)))
|
||||
m.setIsActive(d.getIsActive());
|
||||
if (fields.hasField(this.asIndexer(Annotation._id))) m.setId(d.getId());
|
||||
if (fields.hasField(this.asIndexer(Annotation._entityId))) m.setEntityId(d.getEntityId());
|
||||
if (fields.hasField(this.asIndexer(Annotation._entityType))) m.setEntityType(d.getEntityType());
|
||||
if (fields.hasField(this.asIndexer(Annotation._anchor))) m.setAnchor(d.getAnchor());
|
||||
if (fields.hasField(this.asIndexer(Annotation._payload))) m.setPayload(d.getPayload());
|
||||
if (fields.hasField(this.asIndexer(Annotation._subjectId))) m.setSubjectId(d.getSubjectId());
|
||||
if (fields.hasField(this.asIndexer(Annotation._threadId))) m.setThreadId(d.getThreadId());
|
||||
if (fields.hasField(this.asIndexer(Annotation._parentId))) m.setParentId(d.getParentId());
|
||||
if (fields.hasField(this.asIndexer(Annotation._protectionType))) m.setProtectionType(d.getProtectionType());
|
||||
if (fields.hasField(this.asIndexer(Annotation._timeStamp))) m.setTimeStamp(d.getTimeStamp());
|
||||
if (fields.hasField(this.asIndexer(Annotation._createdAt))) m.setCreatedAt(d.getCreatedAt());
|
||||
if (fields.hasField(this.asIndexer(Annotation._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
|
||||
if (fields.hasField(this.asIndexer(Annotation._isActive))) m.setIsActive(d.getIsActive());
|
||||
if (fields.hasField(this.asIndexer(Annotation._hash))) m.setHash(this.hashValue(d.getUpdatedAt()));
|
||||
if (!authorFields.isEmpty() && authorsMap != null && authorsMap.containsKey(d.getSubjectId())) m.setAuthor(authorsMap.get(d.getSubjectId()));
|
||||
if (affiliatedResourceMap != null && !authorizationFlags.isEmpty()) m.setAuthorizationFlags(this.evaluateAuthorizationFlags(this.authorizationService, authorizationFlags, affiliatedResourceMap.getOrDefault(d.getId(), null)));
|
||||
models.add(m);
|
||||
}
|
||||
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
|
||||
|
@ -103,7 +100,7 @@ public class AnnotationBuilder extends BaseBuilder<Annotation, AnnotationEntity>
|
|||
.map(AnnotationEntity::getSubjectId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
UserQuery query = this.queryFactory.query(UserQuery.class).authorize(this.authorize).ids(userIds);
|
||||
UserQuery query = this.queryFactory.query(UserQuery.class).ids(userIds);
|
||||
Map<UUID, List<User>> users = this.builderFactory.builder(UserBuilder.class).authorize(this.authorize).asMasterKey(query, clone, User::getId);
|
||||
|
||||
users.forEach((key, val) -> {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package gr.cite.annotation.model.builder;
|
||||
|
||||
import gr.cite.annotation.authorization.AffiliatedResource;
|
||||
import gr.cite.annotation.convention.ConventionService;
|
||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||
import gr.cite.tools.data.builder.Builder;
|
||||
import gr.cite.tools.data.query.QueryBase;
|
||||
import gr.cite.tools.exception.MyApplicationException;
|
||||
|
@ -92,4 +94,25 @@ public abstract class BaseBuilder<M, D> implements Builder {
|
|||
return this.conventionService.asIndexer(names);
|
||||
}
|
||||
|
||||
protected Set<String> extractAuthorizationFlags(FieldSet fields, String propertyName, List<String> permissionNames){
|
||||
if (fields == null) return new HashSet<>();
|
||||
if (permissionNames == null) return new HashSet<>();
|
||||
|
||||
FieldSet authorizationFlags = fields.extractPrefixed(this.asPrefix(propertyName));
|
||||
List<String> permissions = new ArrayList<>();
|
||||
for (String fieldValue : authorizationFlags.getFields()) permissions.addAll(permissionNames.stream().filter(x-> x.equalsIgnoreCase(fieldValue)).toList());
|
||||
return new HashSet<>(permissions);
|
||||
}
|
||||
|
||||
protected List<String> evaluateAuthorizationFlags(AuthorizationService authorizationService, Set<String> authorizationFlags, AffiliatedResource affiliatedResource) {
|
||||
List<String> allowed = new ArrayList<>();
|
||||
if (authorizationFlags == null) return allowed;
|
||||
if (authorizationService == null) return allowed;
|
||||
|
||||
for (String permission : authorizationFlags) {
|
||||
Boolean isAllowed = affiliatedResource == null ? authorizationService.authorize(permission) : authorizationService.authorizeAtLeastOne(List.of(affiliatedResource), permission);
|
||||
if (isAllowed) allowed.add(permission);
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package gr.cite.annotation.model.censorship;
|
||||
|
||||
import gr.cite.annotation.authorization.Permission;
|
||||
import gr.cite.annotation.convention.ConventionService;
|
||||
import gr.cite.annotation.model.Annotation;
|
||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||
import gr.cite.tools.fieldset.FieldSet;
|
||||
import gr.cite.tools.logging.DataLogEntry;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class AnnotationAuthorCensor extends BaseCensor{
|
||||
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(AnnotationAuthorCensor.class));
|
||||
|
||||
protected final AuthorizationService authService;
|
||||
|
||||
public AnnotationAuthorCensor(ConventionService conventionService, AuthorizationService authService) {
|
||||
super(conventionService);
|
||||
this.authService = authService;
|
||||
}
|
||||
|
||||
public void censor(FieldSet fields, UUID userId) {
|
||||
logger.debug(new DataLogEntry("censoring fields", fields));
|
||||
if (fields == null || fields.isEmpty())
|
||||
return;
|
||||
|
||||
this.authService.authorizeForce(Permission.BrowseAnnotation, Permission.DeferredAffiliation);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,9 @@ package gr.cite.annotation.model.censorship;
|
|||
|
||||
import gr.cite.annotation.authorization.Permission;
|
||||
import gr.cite.annotation.convention.ConventionService;
|
||||
import gr.cite.annotation.model.Annotation;
|
||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||
import gr.cite.tools.data.censor.CensorFactory;
|
||||
import gr.cite.tools.fieldset.FieldSet;
|
||||
import gr.cite.tools.logging.DataLogEntry;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
|
@ -21,9 +23,12 @@ public class AnnotationCensor extends BaseCensor{
|
|||
|
||||
protected final AuthorizationService authService;
|
||||
|
||||
public AnnotationCensor(ConventionService conventionService, AuthorizationService authService) {
|
||||
protected final CensorFactory censorFactory;
|
||||
|
||||
public AnnotationCensor(ConventionService conventionService, AuthorizationService authService, CensorFactory censorFactory) {
|
||||
super(conventionService);
|
||||
this.authService = authService;
|
||||
this.censorFactory = censorFactory;
|
||||
}
|
||||
|
||||
public void censor(FieldSet fields, UUID userId) {
|
||||
|
@ -31,7 +36,10 @@ public class AnnotationCensor extends BaseCensor{
|
|||
if (fields == null || fields.isEmpty())
|
||||
return;
|
||||
|
||||
this.authService.authorizeForce(Permission.BrowseAnnotation);
|
||||
this.authService.authorizeForce(Permission.BrowseAnnotation, Permission.DeferredAffiliation);
|
||||
|
||||
FieldSet authorFields = fields.extractPrefixed(this.asIndexerPrefix(Annotation._author));
|
||||
this.censorFactory.censor(AnnotationAuthorCensor.class).censor(authorFields, userId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package gr.cite.EntityUser.model.deleter;
|
||||
|
||||
import gr.cite.annotation.common.enums.IsActive;
|
||||
import gr.cite.annotation.data.EntityUserEntity;
|
||||
import gr.cite.annotation.data.TenantScopedEntityManager;
|
||||
import gr.cite.annotation.query.EntityUserQuery;
|
||||
import gr.cite.tools.data.deleter.Deleter;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import gr.cite.tools.logging.MapLogEntry;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.management.InvalidApplicationException;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class EntityUserDeleter implements Deleter {
|
||||
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(EntityUserDeleter.class));
|
||||
|
||||
private final TenantScopedEntityManager entityManager;
|
||||
|
||||
private final QueryFactory queryFactory;
|
||||
|
||||
@Autowired
|
||||
public EntityUserDeleter(
|
||||
TenantScopedEntityManager entityManager,
|
||||
QueryFactory queryFactory
|
||||
) {
|
||||
this.entityManager = entityManager;
|
||||
this.queryFactory = queryFactory;
|
||||
}
|
||||
|
||||
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
|
||||
logger.debug(new MapLogEntry("collecting to delete").And("count", Optional.ofNullable(ids).map(List::size).orElse(0)).And("ids", ids));
|
||||
List<EntityUserEntity> data = this.queryFactory.query(EntityUserQuery.class).ids(ids).collect();
|
||||
logger.trace("retrieved {} items", Optional.ofNullable(data).map(List::size).orElse(0));
|
||||
this.deleteAndSave(data);
|
||||
}
|
||||
|
||||
public void deleteAndSave(List<EntityUserEntity> data) throws InvalidApplicationException {
|
||||
logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0));
|
||||
this.delete(data);
|
||||
logger.trace("saving changes");
|
||||
this.entityManager.flush();
|
||||
logger.trace("changes saved");
|
||||
}
|
||||
|
||||
public void delete(List<EntityUserEntity> data) throws InvalidApplicationException {
|
||||
logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0));
|
||||
if (data == null || data.isEmpty())
|
||||
return;
|
||||
|
||||
Instant now = Instant.now();
|
||||
|
||||
for (EntityUserEntity item : data) {
|
||||
logger.trace("deleting item {}", item);
|
||||
item.setIsActive(IsActive.Inactive);
|
||||
item.setUpdatedAt(now);
|
||||
logger.trace("updating item");
|
||||
this.entityManager.merge(item);
|
||||
logger.trace("updated item");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,16 @@
|
|||
package gr.cite.annotation.query;
|
||||
|
||||
import gr.cite.annotation.authorization.AuthorizationFlags;
|
||||
import gr.cite.annotation.authorization.Permission;
|
||||
import gr.cite.annotation.common.enums.AnnotationProtectionType;
|
||||
import gr.cite.annotation.common.enums.IsActive;
|
||||
import gr.cite.annotation.common.scope.user.UserScope;
|
||||
import gr.cite.annotation.data.AnnotationEntity;
|
||||
import gr.cite.annotation.data.EntityUserEntity;
|
||||
import gr.cite.annotation.model.Annotation;
|
||||
import gr.cite.annotation.model.EntityUser;
|
||||
import gr.cite.annotation.query.utils.BuildSubQueryInput;
|
||||
import gr.cite.annotation.query.utils.QueryUtilsService;
|
||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||
import gr.cite.tools.data.query.FieldResolver;
|
||||
import gr.cite.tools.data.query.QueryBase;
|
||||
|
@ -13,6 +18,7 @@ import gr.cite.tools.data.query.QueryContext;
|
|||
import jakarta.persistence.Tuple;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Subquery;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
@ -44,11 +50,14 @@ public class AnnotationQuery extends QueryBase<AnnotationEntity> {
|
|||
|
||||
private final UserScope userScope;
|
||||
|
||||
private final QueryUtilsService queryUtilsService;
|
||||
|
||||
private final AuthorizationService authService;
|
||||
|
||||
public AnnotationQuery(UserScope userScope, AuthorizationService authService) {
|
||||
public AnnotationQuery(UserScope userScope, QueryUtilsService queryUtilsService, AuthorizationService authService) {
|
||||
this.userScope = userScope;
|
||||
this.authService = authService;
|
||||
this.queryUtilsService = queryUtilsService;
|
||||
this.authService = authService;
|
||||
}
|
||||
|
||||
public AnnotationQuery like(String value) {
|
||||
|
@ -161,6 +170,11 @@ public class AnnotationQuery extends QueryBase<AnnotationEntity> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public AnnotationQuery authorize(EnumSet<AuthorizationFlags> values) {
|
||||
this.authorize = values;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean isFalseQuery() {
|
||||
return this.isEmpty(this.ids) || this.isEmpty(this.excludedIds) || this.isEmpty(this.isActives) || this.isEmpty(this.entityIds);
|
||||
|
@ -171,6 +185,43 @@ public class AnnotationQuery extends QueryBase<AnnotationEntity> {
|
|||
return AnnotationEntity.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.BrowseAnnotation)) return null;
|
||||
UUID userId = null;
|
||||
if (this.authorize.contains(AuthorizationFlags.Associated)) userId = this.userScope.getUserIdSafe();
|
||||
if (this.authorize.contains(AuthorizationFlags.Owner)) userId = this.userScope.getUserIdSafe();
|
||||
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
if (userId != null ) {
|
||||
UUID finalUserId = userId;
|
||||
Subquery<UUID> subquery = this.queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(new BuildSubQueryInput.Builder<>(EntityUserEntity.class, UUID.class)
|
||||
.query(queryContext.Query)
|
||||
.criteriaBuilder(queryContext.CriteriaBuilder)
|
||||
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(EntityUserEntity._entityId))
|
||||
.filterFunc((subQueryRoot, cb) ->
|
||||
cb.and(
|
||||
cb.equal(subQueryRoot.get(EntityUserEntity._userId), finalUserId),
|
||||
cb.equal(subQueryRoot.get(EntityUserEntity._isActive), IsActive.Active)
|
||||
)
|
||||
)
|
||||
));
|
||||
predicates.add(queryContext.CriteriaBuilder.or(
|
||||
queryContext.CriteriaBuilder.in(queryContext.Root.get(AnnotationEntity._subjectId)).value(userId),
|
||||
queryContext.CriteriaBuilder.and(
|
||||
queryContext.CriteriaBuilder.equal(queryContext.Root.get(AnnotationEntity._protectionType), AnnotationProtectionType.EntityAccessors),
|
||||
queryContext.CriteriaBuilder.in(queryContext.Root.get(AnnotationEntity._entityId)).value(subquery)
|
||||
)));
|
||||
}
|
||||
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<>();
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
package gr.cite.annotation.query;
|
||||
|
||||
import gr.cite.annotation.authorization.AuthorizationFlags;
|
||||
import gr.cite.annotation.authorization.Permission;
|
||||
import gr.cite.annotation.common.enums.AnnotationProtectionType;
|
||||
import gr.cite.annotation.common.enums.IsActive;
|
||||
import gr.cite.annotation.common.scope.user.UserScope;
|
||||
import gr.cite.annotation.data.AnnotationEntity;
|
||||
import gr.cite.annotation.data.EntityUserEntity;
|
||||
import gr.cite.annotation.model.EntityUser;
|
||||
import gr.cite.annotation.query.utils.BuildSubQueryInput;
|
||||
import gr.cite.annotation.query.utils.QueryUtilsService;
|
||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||
import gr.cite.tools.data.query.FieldResolver;
|
||||
import gr.cite.tools.data.query.QueryBase;
|
||||
import gr.cite.tools.data.query.QueryContext;
|
||||
|
@ -12,6 +20,7 @@ import jakarta.persistence.criteria.Predicate;
|
|||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.annotation.RequestScope;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
|
@ -20,11 +29,20 @@ public class EntityUserQuery extends QueryBase<EntityUserEntity> {
|
|||
|
||||
private Collection<UUID> ids, entityIds, userIds;
|
||||
|
||||
private Collection<IsActive> isActives;
|
||||
private Collection<IsActive> isActives;;
|
||||
|
||||
private final AuthorizationService authService;
|
||||
|
||||
private final UserScope userScope;
|
||||
|
||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||
|
||||
public EntityUserQuery ids(UUID value) {
|
||||
public EntityUserQuery(AuthorizationService authService, UserScope userScope) {
|
||||
this.authService = authService;
|
||||
this.userScope = userScope;
|
||||
}
|
||||
|
||||
public EntityUserQuery ids(UUID value) {
|
||||
this.ids = List.of(value);
|
||||
return this;
|
||||
}
|
||||
|
@ -98,6 +116,26 @@ public class EntityUserQuery extends QueryBase<EntityUserEntity> {
|
|||
protected Class<EntityUserEntity> entityClass() {
|
||||
return EntityUserEntity.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.BrowseAnnotation)) return null;
|
||||
UUID userId = null;
|
||||
if (this.authorize.contains(AuthorizationFlags.Associated)) userId = this.userScope.getUserIdSafe();
|
||||
if (this.authorize.contains(AuthorizationFlags.Owner)) userId = this.userScope.getUserIdSafe();
|
||||
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
if (userId != null ) {
|
||||
predicates.add( queryContext.CriteriaBuilder.in(queryContext.Root.get(EntityUserEntity._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) {
|
||||
|
@ -136,11 +174,35 @@ public class EntityUserQuery extends QueryBase<EntityUserEntity> {
|
|||
|
||||
@Override
|
||||
protected String fieldNameOf(FieldResolver item) {
|
||||
return null;
|
||||
if (item.match(EntityUser._id))
|
||||
return EntityUserEntity._id;
|
||||
else if (item.match(EntityUser._entityId))
|
||||
return EntityUserEntity._entityId;
|
||||
else if (item.match(EntityUser._user))
|
||||
return EntityUserEntity._userId;
|
||||
else if (item.prefix(EntityUser._user))
|
||||
return EntityUserEntity._userId;
|
||||
else if (item.match(EntityUser._createdAt))
|
||||
return EntityUserEntity._createdAt;
|
||||
else if (item.match(EntityUser._updatedAt))
|
||||
return EntityUserEntity._updatedAt;
|
||||
else if (item.match(EntityUser._hash))
|
||||
return EntityUserEntity._updatedAt;
|
||||
else if (item.match(EntityUser._isActive))
|
||||
return EntityUserEntity._isActive;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EntityUserEntity convert(Tuple tuple, Set<String> columns) {
|
||||
return null;
|
||||
EntityUserEntity item = new EntityUserEntity();
|
||||
item.setId(QueryBase.convertSafe(tuple, columns, EntityUserEntity._id, UUID.class));
|
||||
item.setEntityId(QueryBase.convertSafe(tuple, columns, EntityUserEntity._entityId, UUID.class));
|
||||
item.setUserId(QueryBase.convertSafe(tuple, columns, EntityUserEntity._userId, UUID.class));
|
||||
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, EntityUserEntity._createdAt, Instant.class));
|
||||
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, EntityUserEntity._updatedAt, Instant.class));
|
||||
item.setIsActive(QueryBase.convertSafe(tuple, columns, EntityUserEntity._isActive, IsActive.class));
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package gr.cite.annotation.query.utils;
|
||||
|
||||
import gr.cite.tools.data.query.QueryContext;
|
||||
import jakarta.persistence.criteria.*;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class BuildSubQueryInput<Entity, Key> {
|
||||
private final AbstractQuery<?> query;
|
||||
private final CriteriaBuilder criteriaBuilder;
|
||||
private final Class<Entity> entityType;
|
||||
private final Class<Key> keyType;
|
||||
private final Function<Root<Entity>, Expression<Key>> keyPathFunc;
|
||||
private final BiFunction<Root<Entity>, CriteriaBuilder, Predicate> filterFunc;
|
||||
|
||||
public BuildSubQueryInput(Builder<Entity, Key> builder) {
|
||||
query = builder.query;
|
||||
criteriaBuilder = builder.criteriaBuilder;
|
||||
entityType = builder.entityType;
|
||||
keyType = builder.keyType;
|
||||
keyPathFunc = builder.keyPathFunc;
|
||||
filterFunc = builder.filterFunc;
|
||||
}
|
||||
|
||||
public AbstractQuery<?> getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public CriteriaBuilder getCriteriaBuilder() {
|
||||
return criteriaBuilder;
|
||||
}
|
||||
|
||||
public Class<Entity> getEntityType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
public Class<Key> getKeyType() {
|
||||
return keyType;
|
||||
}
|
||||
|
||||
public Function<Root<Entity>, Expression<Key>> getKeyPathFunc() {
|
||||
return keyPathFunc;
|
||||
}
|
||||
|
||||
public BiFunction<Root<Entity>, CriteriaBuilder, Predicate> getFilterFunc() {
|
||||
return filterFunc;
|
||||
}
|
||||
|
||||
public static class Builder<Entity, Key> {
|
||||
private final Class<Entity> entityType;
|
||||
private final Class<Key> keyType;
|
||||
private AbstractQuery<?> query;
|
||||
private CriteriaBuilder criteriaBuilder;
|
||||
private Function<Root<Entity>, Expression<Key>> keyPathFunc;
|
||||
private BiFunction<Root<Entity>, CriteriaBuilder, Predicate> filterFunc;
|
||||
|
||||
public Builder(Class<Entity> entityType, Class<Key> keyType) {
|
||||
this.entityType = entityType;
|
||||
this.keyType = keyType;
|
||||
}
|
||||
|
||||
public Builder(Class<Entity> entityType, Class<Key> keyType, QueryContext<?, ?> queryContext) {
|
||||
this.entityType = entityType;
|
||||
this.keyType = keyType;
|
||||
this.query = queryContext.Query;
|
||||
this.criteriaBuilder = queryContext.CriteriaBuilder;
|
||||
}
|
||||
|
||||
public Builder<Entity, Key> query(AbstractQuery<?> query) {
|
||||
this.query = query;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<Entity, Key> criteriaBuilder(CriteriaBuilder criteriaBuilder) {
|
||||
this.criteriaBuilder = criteriaBuilder;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<Entity, Key> keyPathFunc(Function<Root<Entity>, Expression<Key>> keyPathFunc) {
|
||||
this.keyPathFunc = keyPathFunc;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<Entity, Key> filterFunc(BiFunction<Root<Entity>, CriteriaBuilder, Predicate> filterFunc) {
|
||||
this.filterFunc = filterFunc;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package gr.cite.annotation.query.utils;
|
||||
|
||||
import jakarta.persistence.criteria.AbstractQuery;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.Subquery;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface QueryUtilsService {
|
||||
<Key, D> Subquery<Key> buildSubQuery(BuildSubQueryInput<D, Key> parameters);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package gr.cite.annotation.query.utils;
|
||||
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.criteria.Subquery;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
public class QueryUtilsServiceImpl implements QueryUtilsService {
|
||||
@Override
|
||||
public <Key, D> Subquery<Key> buildSubQuery(BuildSubQueryInput<D, Key> parameters){
|
||||
Subquery<Key> subQuery = parameters.getQuery().subquery(parameters.getKeyType());
|
||||
Root<D> subQueryRoot = subQuery.from(parameters.getEntityType());
|
||||
subQuery.select(parameters.getKeyPathFunc().apply(subQueryRoot)).distinct(true);
|
||||
subQuery.where(parameters.getFilterFunc().apply(subQueryRoot, parameters.getCriteriaBuilder()));
|
||||
return subQuery;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package gr.cite.annotation.service.annotation;
|
||||
|
||||
import gr.cite.annotation.authorization.AuthorizationFlags;
|
||||
import gr.cite.annotation.authorization.OwnedResource;
|
||||
import gr.cite.annotation.authorization.Permission;
|
||||
import gr.cite.annotation.authorization.authorizationcontentresolver.AuthorizationContentResolver;
|
||||
import gr.cite.annotation.common.enums.IsActive;
|
||||
import gr.cite.annotation.common.scope.user.UserScope;
|
||||
import gr.cite.annotation.data.AnnotationEntity;
|
||||
|
@ -23,6 +25,8 @@ import gr.cite.tools.logging.MapLogEntry;
|
|||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.management.InvalidApplicationException;
|
||||
|
@ -45,17 +49,23 @@ public class AnnotationServiceImpl implements AnnotationService {
|
|||
private final BuilderFactory builderFactory;
|
||||
|
||||
private final UserScope userScope;
|
||||
private final AuthorizationContentResolver authorizationContentResolver;
|
||||
|
||||
private final MessageSource messageSource;
|
||||
|
||||
|
||||
public AnnotationServiceImpl(
|
||||
AuthorizationService authorizationService,
|
||||
DeleterFactory deleterFactory,
|
||||
EntityManager entityManager,
|
||||
BuilderFactory builderFactory, UserScope userScope) {
|
||||
AuthorizationService authorizationService,
|
||||
DeleterFactory deleterFactory,
|
||||
EntityManager entityManager,
|
||||
BuilderFactory builderFactory, UserScope userScope, AuthorizationContentResolver authorizationContentResolver, MessageSource messageSource) {
|
||||
this.authorizationService = authorizationService;
|
||||
this.deleterFactory = deleterFactory;
|
||||
this.entityManager = entityManager;
|
||||
this.builderFactory = builderFactory;
|
||||
this.userScope = userScope;
|
||||
this.authorizationContentResolver = authorizationContentResolver;
|
||||
this.messageSource = messageSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -63,7 +73,7 @@ public class AnnotationServiceImpl implements AnnotationService {
|
|||
public Annotation persist(AnnotationPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException {
|
||||
logger.debug(new MapLogEntry("persisting annotation").And("model", model).And("fields", fields));
|
||||
|
||||
this.authorizationService.authorizeForce(Permission.EditAnnotation);
|
||||
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.entityAffiliation(model.getEntityId())), Permission.NewAnnotation);
|
||||
|
||||
AnnotationEntity data = new AnnotationEntity();
|
||||
data.setId(UUID.randomUUID());
|
||||
|
@ -91,7 +101,10 @@ public class AnnotationServiceImpl implements AnnotationService {
|
|||
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
|
||||
logger.debug("deleting Annotation: {}", id);
|
||||
|
||||
this.authorizationService.authorizeForce(Permission.DeleteAnnotation);
|
||||
AnnotationEntity annotation = this.entityManager.find(AnnotationEntity.class, id);
|
||||
if (annotation == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Annotation.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
this.authorizationService.authorizeAtLeastOneForce(annotation.getSubjectId() != null ? List.of(new OwnedResource(annotation.getSubjectId())) : null, Permission.DeleteAnnotation);
|
||||
|
||||
this.deleterFactory.deleter(AnnotationDeleter.class).deleteAndSaveByIds(List.of(id));
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<version>3.2.1</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@ -136,18 +136,18 @@
|
|||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
<artifactId>rabbitmq-core</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<version>2.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
<artifactId>queue-inbox</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>2.1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
<artifactId>queue-outbox</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>2.1.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
|
|
@ -65,12 +65,12 @@
|
|||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
<artifactId>queue-inbox</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>2.1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
<artifactId>queue-outbox</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>2.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
|
|
@ -16,7 +16,7 @@ import java.util.List;
|
|||
@Service
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
|
||||
public class PermissionNameProvider {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DepositServiceImpl.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(PermissionNameProvider.class);
|
||||
private final List<String> permissions;
|
||||
|
||||
public PermissionNameProvider(ConventionService conventionService) {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package eu.eudat.configurations.db;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.bind.ConstructorBinding;
|
||||
|
||||
@ConfigurationProperties(prefix = "naming-strategy")
|
||||
public class NamingStrategyProperties {
|
||||
|
||||
private final String prefix;
|
||||
|
||||
@ConstructorBinding
|
||||
public NamingStrategyProperties(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package eu.eudat.configurations.db;
|
||||
|
||||
import eu.eudat.convention.ConventionService;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@EnableConfigurationProperties({NamingStrategyProperties.class})
|
||||
public class PrefixPhysicalNamingStrategy extends PhysicalNamingStrategyStandardImpl {
|
||||
|
||||
private final NamingStrategyProperties namingStrategyProperties;
|
||||
private final ConventionService conventionService;
|
||||
|
||||
public PrefixPhysicalNamingStrategy(NamingStrategyProperties namingStrategyProperties, ConventionService conventionService) {
|
||||
this.namingStrategyProperties = namingStrategyProperties;
|
||||
this.conventionService = conventionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier toPhysicalTableName(Identifier logicalName, JdbcEnvironment context) {
|
||||
if (conventionService.isNullOrEmpty(namingStrategyProperties.getPrefix()))
|
||||
return super.toPhysicalTableName(logicalName, context);
|
||||
Identifier identifier = new Identifier(namingStrategyProperties.getPrefix() + logicalName.getText(), logicalName.isQuoted());
|
||||
return super.toPhysicalTableName(identifier, context);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@ package eu.eudat.data;
|
|||
|
||||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.data.converters.enums.IsActiveConverter;
|
||||
import eu.eudat.data.converters.enums.QueueInboxStatusConverter;
|
||||
import eu.eudat.data.types.JsonSQLType;
|
||||
import gr.cite.queueinbox.entity.QueueInbox;
|
||||
import gr.cite.queueinbox.entity.QueueInboxStatus;
|
||||
|
@ -19,15 +20,15 @@ public class QueueInboxEntity implements QueueInbox {
|
|||
private UUID id;
|
||||
public final static String _id = "id";
|
||||
|
||||
@Column(name = "\"queue\"", nullable = false, length = 50)
|
||||
@Column(name = "\"queue\"", nullable = false, length = 200)
|
||||
private String queue;
|
||||
public final static String _queue = "queue";
|
||||
|
||||
@Column(name = "\"exchange\"", nullable = false, length = 50)
|
||||
@Column(name = "\"exchange\"", nullable = false, length = 200)
|
||||
private String exchange;
|
||||
public final static String _exchange = "exchange";
|
||||
|
||||
@Column(name = "\"route\"", nullable = false, length = 50)
|
||||
@Column(name = "\"route\"", nullable = false, length = 200)
|
||||
private String route;
|
||||
public final static String _route = "route";
|
||||
|
||||
|
@ -52,14 +53,13 @@ public class QueueInboxEntity implements QueueInbox {
|
|||
private UUID tenantId;
|
||||
public final static String _tenantId = "tenantId";
|
||||
|
||||
@Column(name = "\"is_active\"", length = 20, nullable = false)
|
||||
@Column(name = "\"is_active\"", nullable = false)
|
||||
@Convert(converter = IsActiveConverter.class)
|
||||
private IsActive isActive;
|
||||
public final static String _isActive = "isActive";
|
||||
|
||||
//TODO: as integer
|
||||
@Column(name = "\"status\"", length = 50, nullable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "\"status\"", nullable = false)
|
||||
@Convert(converter = QueueInboxStatusConverter.class)
|
||||
private QueueInboxStatus status;
|
||||
public final static String _status = "status";
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package eu.eudat.data;
|
|||
|
||||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.data.converters.enums.IsActiveConverter;
|
||||
import eu.eudat.data.converters.enums.QueueOutboxNotifyStatusConverter;
|
||||
import gr.cite.queueoutbox.entity.QueueOutbox;
|
||||
import gr.cite.queueoutbox.entity.QueueOutboxNotifyStatus;
|
||||
|
||||
|
@ -17,11 +18,11 @@ public class QueueOutboxEntity implements QueueOutbox {
|
|||
private UUID id;
|
||||
public final static String _id = "id";
|
||||
|
||||
@Column(name = "\"exchange\"", nullable = false, length = 50)
|
||||
@Column(name = "\"exchange\"", nullable = false, length = 200)
|
||||
private String exchange;
|
||||
public final static String _exchange = "exchange";
|
||||
|
||||
@Column(name = "\"route\"", length = 50)
|
||||
@Column(name = "\"route\"", length = 200)
|
||||
private String route;
|
||||
public final static String _route = "route";
|
||||
|
||||
|
@ -33,9 +34,8 @@ public class QueueOutboxEntity implements QueueOutbox {
|
|||
private String message;
|
||||
public final static String _message = "message";
|
||||
|
||||
//TODO: as integer
|
||||
@Column(name = "\"notify_status\"", length = 20, nullable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "\"notify_status\"", nullable = false)
|
||||
@Convert(converter = QueueOutboxNotifyStatusConverter.class)
|
||||
private QueueOutboxNotifyStatus notifyStatus;
|
||||
public final static String _notifyStatus = "notifyStatus";
|
||||
|
||||
|
@ -55,7 +55,7 @@ public class QueueOutboxEntity implements QueueOutbox {
|
|||
private UUID tenantId;
|
||||
public final static String _tenantId = "tenantId";
|
||||
|
||||
@Column(name = "\"is_active\"", length = 20, nullable = false)
|
||||
@Column(name = "\"is_active\"", nullable = false)
|
||||
@Convert(converter = IsActiveConverter.class)
|
||||
private IsActive isActive;
|
||||
public final static String _isActive = "isActive";
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package eu.eudat.data.converters.enums;
|
||||
|
||||
import gr.cite.queueinbox.entity.QueueInboxStatus;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
@Converter
|
||||
public class QueueInboxStatusConverter implements AttributeConverter<QueueInboxStatus, Short> {
|
||||
@Override
|
||||
public Short convertToDatabaseColumn(QueueInboxStatus value) {
|
||||
if (value == null) throw new IllegalArgumentException("Value could not be null for: " + this.getClass().getSimpleName());
|
||||
return value.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueueInboxStatus convertToEntityAttribute(Short dbData) {
|
||||
return QueueInboxStatus.of(dbData);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package eu.eudat.data.converters.enums;
|
||||
|
||||
import gr.cite.queueoutbox.entity.QueueOutboxNotifyStatus;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
@Converter
|
||||
public class QueueOutboxNotifyStatusConverter implements AttributeConverter<QueueOutboxNotifyStatus, Short> {
|
||||
@Override
|
||||
public Short convertToDatabaseColumn(QueueOutboxNotifyStatus value) {
|
||||
if (value == null) throw new IllegalArgumentException("Value could not be null for: " + this.getClass().getSimpleName());
|
||||
return value.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueueOutboxNotifyStatus convertToEntityAttribute(Short dbData) {
|
||||
return QueueOutboxNotifyStatus.of(dbData);
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ public class OutboxIntegrationEvent extends IntegrationEvent {
|
|||
public static final String DESCRIPTION_TOUCH = "DESCRIPTION_TOUCH";
|
||||
|
||||
public static final String ANNOTATION_ENTITY_TOUCH = "ANNOTATION_ENTITY_TOUCH";
|
||||
public static final String ANNOTATION_ENTITY_REMOVE = "ANNOTATION_ENTITY_REMOVE";
|
||||
|
||||
public static final String WHAT_YOU_KNOW_ABOUT_ME_COMPLETED = "WHAT_YOU_KNOW_ABOUT_ME_COMPLETED";
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ public class OutboxProperties {
|
|||
|
||||
private final String descriptionTouchTopic;
|
||||
|
||||
private final String annotationEntityTouchTopic;
|
||||
private final String annotationEntitiesTouchTopic;
|
||||
private final String annotationEntitiesRemovalTopic;
|
||||
|
||||
private final String notifyTopic;
|
||||
|
||||
|
@ -34,19 +35,20 @@ public class OutboxProperties {
|
|||
private final String generateFileTopic;
|
||||
|
||||
public OutboxProperties(String exchange,
|
||||
String tenantTouchTopic,
|
||||
String tenantRemovalTopic,
|
||||
String tenantReactivationTopic,
|
||||
String tenantUserInviteTopic,
|
||||
String userRemovalTopic,
|
||||
String userTouchTopic,
|
||||
String dmpTouchTopic,
|
||||
String descriptionTouchTopic,
|
||||
String annotationEntityTouchTopic,
|
||||
String notifyTopic,
|
||||
String forgetMeCompletedTopic,
|
||||
String whatYouKnowAboutMeCompletedTopic,
|
||||
String generateFileTopic
|
||||
String tenantTouchTopic,
|
||||
String tenantRemovalTopic,
|
||||
String tenantReactivationTopic,
|
||||
String tenantUserInviteTopic,
|
||||
String userRemovalTopic,
|
||||
String userTouchTopic,
|
||||
String dmpTouchTopic,
|
||||
String descriptionTouchTopic,
|
||||
String annotationEntitiesTouchTopic,
|
||||
String annotationEntitiesRemovalTopic,
|
||||
String notifyTopic,
|
||||
String forgetMeCompletedTopic,
|
||||
String whatYouKnowAboutMeCompletedTopic,
|
||||
String generateFileTopic
|
||||
) {
|
||||
this.exchange = exchange;
|
||||
this.tenantTouchTopic = tenantTouchTopic;
|
||||
|
@ -57,8 +59,9 @@ public class OutboxProperties {
|
|||
this.userTouchTopic = userTouchTopic;
|
||||
this.dmpTouchTopic = dmpTouchTopic;
|
||||
this.descriptionTouchTopic = descriptionTouchTopic;
|
||||
this.annotationEntityTouchTopic = annotationEntityTouchTopic;
|
||||
this.notifyTopic = notifyTopic;
|
||||
this.annotationEntitiesTouchTopic = annotationEntitiesTouchTopic;
|
||||
this.annotationEntitiesRemovalTopic = annotationEntitiesRemovalTopic;
|
||||
this.notifyTopic = notifyTopic;
|
||||
this.forgetMeCompletedTopic = forgetMeCompletedTopic;
|
||||
this.whatYouKnowAboutMeCompletedTopic = whatYouKnowAboutMeCompletedTopic;
|
||||
this.generateFileTopic = generateFileTopic;
|
||||
|
@ -100,8 +103,12 @@ public class OutboxProperties {
|
|||
return descriptionTouchTopic;
|
||||
}
|
||||
|
||||
public String getAnnotationEntityTouchTopic() {
|
||||
return annotationEntityTouchTopic;
|
||||
public String getAnnotationEntitiesTouchTopic() {
|
||||
return annotationEntitiesTouchTopic;
|
||||
}
|
||||
|
||||
public String getAnnotationEntitiesRemovalTopic() {
|
||||
return annotationEntitiesRemovalTopic;
|
||||
}
|
||||
|
||||
public String getNotifyTopic() {
|
||||
|
|
|
@ -416,7 +416,11 @@ public class OutboxRepositoryImpl implements OutboxRepository {
|
|||
break;
|
||||
}
|
||||
case OutboxIntegrationEvent.ANNOTATION_ENTITY_TOUCH: {
|
||||
routingKey = this.outboxProperties.getAnnotationEntityTouchTopic();
|
||||
routingKey = this.outboxProperties.getAnnotationEntitiesTouchTopic();
|
||||
break;
|
||||
}
|
||||
case OutboxIntegrationEvent.ANNOTATION_ENTITY_REMOVE: {
|
||||
routingKey = this.outboxProperties.getAnnotationEntitiesRemovalTopic();
|
||||
break;
|
||||
}
|
||||
case OutboxIntegrationEvent.FORGET_ME_COMPLETED: {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package eu.eudat.integrationevent.outbox.annotationentityremoval;
|
||||
|
||||
import eu.eudat.integrationevent.TrackedEvent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AnnotationEntitiesRemovalIntegrationEvent extends TrackedEvent {
|
||||
|
||||
private List<UUID> entityIds;
|
||||
|
||||
public List<UUID> getEntityIds() {
|
||||
return entityIds;
|
||||
}
|
||||
|
||||
public void setEntityIds(List<UUID> entityIds) {
|
||||
this.entityIds = entityIds;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package eu.eudat.integrationevent.outbox.annotationentityremoval;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface AnnotationEntityRemovalIntegrationEventHandler {
|
||||
|
||||
void handleDescription(UUID descriptionId);
|
||||
void handleDmp(UUID dmpId);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package eu.eudat.integrationevent.outbox.annotationentityremoval;
|
||||
|
||||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.data.DescriptionEntity;
|
||||
import eu.eudat.data.DmpUserEntity;
|
||||
import eu.eudat.integrationevent.outbox.OutboxIntegrationEvent;
|
||||
import eu.eudat.integrationevent.outbox.OutboxService;
|
||||
import eu.eudat.model.Description;
|
||||
import eu.eudat.model.DmpUser;
|
||||
import eu.eudat.query.DescriptionQuery;
|
||||
import eu.eudat.query.DmpUserQuery;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class AnnotationEntityRemovalIntegrationEventHandlerImpl implements AnnotationEntityRemovalIntegrationEventHandler {
|
||||
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(AnnotationEntityRemovalIntegrationEventHandlerImpl.class));
|
||||
|
||||
private final OutboxService outboxService;
|
||||
|
||||
private final QueryFactory queryFactory;
|
||||
|
||||
public AnnotationEntityRemovalIntegrationEventHandlerImpl(OutboxService outboxService, QueryFactory queryFactory) {
|
||||
this.outboxService = outboxService;
|
||||
this.queryFactory = queryFactory;
|
||||
}
|
||||
|
||||
private void handle(AnnotationEntitiesRemovalIntegrationEvent event) {
|
||||
OutboxIntegrationEvent message = new OutboxIntegrationEvent();
|
||||
message.setMessageId(UUID.randomUUID());
|
||||
message.setType(OutboxIntegrationEvent.ANNOTATION_ENTITY_REMOVE);
|
||||
message.setEvent(event);
|
||||
this.outboxService.publish(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleDescription(UUID descriptionId) {
|
||||
AnnotationEntitiesRemovalIntegrationEvent event = new AnnotationEntitiesRemovalIntegrationEvent();
|
||||
event.setEntityIds(List.of(descriptionId));
|
||||
|
||||
this.handle(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleDmp(UUID dmpId) {
|
||||
List<DescriptionEntity> descriptionEntities = this.queryFactory.query(DescriptionQuery.class).dmpIds(dmpId).collectAs(new BaseFieldSet().ensure(Description._id));
|
||||
|
||||
AnnotationEntitiesRemovalIntegrationEvent event = new AnnotationEntitiesRemovalIntegrationEvent();
|
||||
event.setEntityIds(new ArrayList<>());
|
||||
event.getEntityIds().add(dmpId);
|
||||
|
||||
for (DescriptionEntity description : descriptionEntities) event.getEntityIds().add(description.getId());
|
||||
|
||||
this.handle(event);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package eu.eudat.integrationevent.outbox.annotationentitytouch;
|
||||
|
||||
import eu.eudat.integrationevent.TrackedEvent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AnnotationEntitiesTouchedIntegrationEvent extends TrackedEvent {
|
||||
|
||||
private List<AnnotationEntityTouchedIntegrationEvent> events;
|
||||
|
||||
public List<AnnotationEntityTouchedIntegrationEvent> getEvents() {
|
||||
return events;
|
||||
}
|
||||
|
||||
public void setEvents(List<AnnotationEntityTouchedIntegrationEvent> events) {
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
public static class AnnotationEntityTouchedIntegrationEvent {
|
||||
|
||||
private UUID entityId;
|
||||
|
||||
private List<UUID> userIds;
|
||||
|
||||
public UUID getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public void setEntityId(UUID entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
public List<UUID> getUserIds() {
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public void setUserIds(List<UUID> userIds) {
|
||||
this.userIds = userIds;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package eu.eudat.integrationevent.outbox.annotationentitytouch;
|
||||
|
||||
import eu.eudat.integrationevent.TrackedEvent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AnnotationEntityTouchedIntegrationEvent extends TrackedEvent {
|
||||
|
||||
private UUID entityId;
|
||||
|
||||
private List<UUID> userIds;
|
||||
|
||||
public UUID getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public void setEntityId(UUID entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
public List<UUID> getUserIds() {
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public void setUserIds(List<UUID> userIds) {
|
||||
this.userIds = userIds;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,17 +9,6 @@ import java.util.UUID;
|
|||
|
||||
public interface AnnotationEntityTouchedIntegrationEventHandler {
|
||||
|
||||
void handle(AnnotationEntityTouchedIntegrationEvent event);
|
||||
|
||||
static AnnotationEntityTouchedIntegrationEvent buildEventFromPersistModel(DmpPersist persist) {
|
||||
AnnotationEntityTouchedIntegrationEvent event = new AnnotationEntityTouchedIntegrationEvent();
|
||||
event.setEntityId(persist.getId());
|
||||
List<UUID> users = new ArrayList<>();
|
||||
persist.getUsers().forEach(dmpUserPersist -> {
|
||||
users.add(dmpUserPersist.getUser());
|
||||
});
|
||||
event.setUserIds(users);
|
||||
return event;
|
||||
}
|
||||
|
||||
void handleDescription(UUID descriptionId);
|
||||
void handleDmp(UUID dmpId);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,24 @@
|
|||
package eu.eudat.integrationevent.outbox.annotationentitytouch;
|
||||
|
||||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.data.DescriptionEntity;
|
||||
import eu.eudat.data.DmpUserEntity;
|
||||
import eu.eudat.integrationevent.outbox.OutboxIntegrationEvent;
|
||||
import eu.eudat.integrationevent.outbox.OutboxService;
|
||||
import eu.eudat.model.Description;
|
||||
import eu.eudat.model.DmpUser;
|
||||
import eu.eudat.query.DescriptionQuery;
|
||||
import eu.eudat.query.DmpUserQuery;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
|
@ -18,12 +29,14 @@ public class AnnotationEntityTouchedIntegrationEventHandlerImpl implements Annot
|
|||
|
||||
private final OutboxService outboxService;
|
||||
|
||||
public AnnotationEntityTouchedIntegrationEventHandlerImpl(OutboxService outboxService) {
|
||||
private final QueryFactory queryFactory;
|
||||
|
||||
public AnnotationEntityTouchedIntegrationEventHandlerImpl(OutboxService outboxService, QueryFactory queryFactory) {
|
||||
this.outboxService = outboxService;
|
||||
this.queryFactory = queryFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(AnnotationEntityTouchedIntegrationEvent event) {
|
||||
private void handle(AnnotationEntitiesTouchedIntegrationEvent event) {
|
||||
OutboxIntegrationEvent message = new OutboxIntegrationEvent();
|
||||
message.setMessageId(UUID.randomUUID());
|
||||
message.setType(OutboxIntegrationEvent.ANNOTATION_ENTITY_TOUCH);
|
||||
|
@ -31,4 +44,40 @@ public class AnnotationEntityTouchedIntegrationEventHandlerImpl implements Annot
|
|||
this.outboxService.publish(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleDescription(UUID descriptionId) {
|
||||
DescriptionEntity entity = this.queryFactory.query(DescriptionQuery.class).ids(descriptionId).firstAs(new BaseFieldSet().ensure(Description._dmp));
|
||||
if (entity == null) return;
|
||||
List<DmpUserEntity> dmpUsers = this.queryFactory.query(DmpUserQuery.class).dmpIds(entity.getDmpId()).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(DmpUser._user));
|
||||
|
||||
AnnotationEntitiesTouchedIntegrationEvent event = new AnnotationEntitiesTouchedIntegrationEvent();
|
||||
event.setEvents(List.of(this.buildEventItem(descriptionId, dmpUsers)));
|
||||
|
||||
this.handle(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleDmp(UUID dmpId) {
|
||||
List<DescriptionEntity> descriptionEntities = this.queryFactory.query(DescriptionQuery.class).dmpIds(dmpId).collectAs(new BaseFieldSet().ensure(Description._id));
|
||||
List<DmpUserEntity> dmpUsers = this.queryFactory.query(DmpUserQuery.class).dmpIds(dmpId).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(DmpUser._user));
|
||||
|
||||
AnnotationEntitiesTouchedIntegrationEvent event = new AnnotationEntitiesTouchedIntegrationEvent();
|
||||
event.setEvents(new ArrayList<>());
|
||||
event.getEvents().add(this.buildEventItem(dmpId, dmpUsers));
|
||||
|
||||
for (DescriptionEntity description : descriptionEntities) event.getEvents().add(this.buildEventItem(description.getId(), dmpUsers));
|
||||
|
||||
this.handle(event);
|
||||
}
|
||||
|
||||
private AnnotationEntitiesTouchedIntegrationEvent.AnnotationEntityTouchedIntegrationEvent buildEventItem(UUID entityId, List<DmpUserEntity> dmpUsers){
|
||||
AnnotationEntitiesTouchedIntegrationEvent.AnnotationEntityTouchedIntegrationEvent eventItem = new AnnotationEntitiesTouchedIntegrationEvent.AnnotationEntityTouchedIntegrationEvent();
|
||||
eventItem.setEntityId(entityId);
|
||||
List<UUID> users = new ArrayList<>();
|
||||
for (DmpUserEntity dmpUser : dmpUsers){
|
||||
users.add(dmpUser.getUserId());
|
||||
}
|
||||
eventItem.setUserIds(users);
|
||||
return eventItem;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,9 @@ public class PublicDmp {
|
|||
private List<PublicDescription> descriptions;
|
||||
public static final String _descriptions = "descriptions";
|
||||
|
||||
private List<PublicEntityDoi> entityDois;
|
||||
public static final String _entityDois = "entityDois";
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -160,4 +163,12 @@ public class PublicDmp {
|
|||
public void setDescriptions(List<PublicDescription> descriptions) {
|
||||
this.descriptions = descriptions;
|
||||
}
|
||||
|
||||
public List<PublicEntityDoi> getEntityDois() {
|
||||
return entityDois;
|
||||
}
|
||||
|
||||
public void setEntityDois(List<PublicEntityDoi> entityDois) {
|
||||
this.entityDois = entityDois;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package eu.eudat.model;
|
||||
|
||||
import eu.eudat.commons.enums.EntityType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PublicEntityDoi {
|
||||
|
||||
private UUID id;
|
||||
|
||||
public static final String _id = "id";
|
||||
|
||||
private EntityType entityType;
|
||||
|
||||
public static final String _entityType = "entityType";
|
||||
|
||||
private String repositoryId;
|
||||
|
||||
public static final String _repositoryId = "repositoryId";
|
||||
|
||||
private String doi;
|
||||
|
||||
public static final String _doi = "doi";
|
||||
|
||||
private UUID entityId;
|
||||
|
||||
public static final String _entityId = "entityId";
|
||||
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public EntityType getEntityType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
public void setEntityType(EntityType entityType) {
|
||||
this.entityType = entityType;
|
||||
}
|
||||
|
||||
public String getRepositoryId() {
|
||||
return repositoryId;
|
||||
}
|
||||
|
||||
public void setRepositoryId(String repositoryId) {
|
||||
this.repositoryId = repositoryId;
|
||||
}
|
||||
|
||||
public String getDoi() {
|
||||
return doi;
|
||||
}
|
||||
|
||||
public void setDoi(String doi) {
|
||||
this.doi = doi;
|
||||
}
|
||||
|
||||
public UUID getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public void setEntityId(UUID entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
package eu.eudat.model.builder;
|
||||
|
||||
import eu.eudat.authorization.AuthorizationFlags;
|
||||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.commons.enums.EntityType;
|
||||
import eu.eudat.convention.ConventionService;
|
||||
import eu.eudat.data.DmpEntity;
|
||||
import eu.eudat.model.*;
|
||||
import eu.eudat.query.DescriptionQuery;
|
||||
import eu.eudat.query.DmpReferenceQuery;
|
||||
import eu.eudat.query.DmpUserQuery;
|
||||
import eu.eudat.query.EntityDoiQuery;
|
||||
import gr.cite.tools.data.builder.BuilderFactory;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.exception.MyApplicationException;
|
||||
|
@ -66,6 +67,9 @@ public class PublicDmpBuilder extends BaseBuilder<PublicDmp, DmpEntity> {
|
|||
FieldSet descriptionsFields = fields.extractPrefixed(this.asPrefix(PublicDmp._descriptions));
|
||||
Map<UUID, List<PublicDescription>> descriptionsMap = this.collectDmpDescriptions(descriptionsFields, data);
|
||||
|
||||
FieldSet entityDoisFields = fields.extractPrefixed(this.asPrefix(PublicDmp._entityDois));
|
||||
Map<UUID, List<PublicEntityDoi>> entityDoisMap = this.collectEntityDois(entityDoisFields, data);
|
||||
|
||||
for (DmpEntity d : data) {
|
||||
PublicDmp m = new PublicDmp();
|
||||
if (fields.hasField(this.asIndexer(PublicDmp._id))) m.setId(d.getId());
|
||||
|
@ -82,6 +86,7 @@ public class PublicDmpBuilder extends BaseBuilder<PublicDmp, DmpEntity> {
|
|||
if (dmpReferenceMap != null && !dmpReferenceMap.isEmpty() && dmpReferenceMap.containsKey(d.getId())) m.setDmpReferences(dmpReferenceMap.get(d.getId()));
|
||||
if (dmpUsersMap != null && !dmpUsersMap.isEmpty() && dmpUsersMap.containsKey(d.getId())) m.setDmpUsers(dmpUsersMap.get(d.getId()));
|
||||
if (descriptionsMap != null && !descriptionsMap.isEmpty() && descriptionsMap.containsKey(d.getId())) m.setDescriptions(descriptionsMap.get(d.getId()));
|
||||
if (entityDoisMap != null && !entityDoisMap.isEmpty() && entityDoisMap.containsKey(d.getId())) m.setEntityDois(entityDoisMap.get(d.getId()));
|
||||
|
||||
models.add(m);
|
||||
}
|
||||
|
@ -144,4 +149,22 @@ public class PublicDmpBuilder extends BaseBuilder<PublicDmp, DmpEntity> {
|
|||
return itemMap;
|
||||
}
|
||||
|
||||
private Map<UUID, List<PublicEntityDoi>> collectEntityDois(FieldSet fields, List<DmpEntity> data) throws MyApplicationException {
|
||||
if (fields.isEmpty() || data.isEmpty()) return null;
|
||||
this.logger.debug("checking related - {}", PublicEntityDoi.class.getSimpleName());
|
||||
|
||||
Map<UUID, List<PublicEntityDoi>> itemMap;
|
||||
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(this.asIndexer(PublicEntityDoi._entityId));
|
||||
EntityDoiQuery query = this.queryFactory.query(EntityDoiQuery.class).authorize(this.authorize).types(EntityType.DMP).entityIds(data.stream().map(DmpEntity::getId).distinct().collect(Collectors.toList()));
|
||||
itemMap = this.builderFactory.builder(PublicEntityDoiBuilder.class).authorize(this.authorize).asMasterKey(query, clone, PublicEntityDoi::getEntityId);
|
||||
|
||||
if (!fields.hasField(this.asIndexer(PublicEntityDoi._entityId))) {
|
||||
itemMap.values().stream().flatMap(List::stream).filter(x -> x != null && x.getEntityId() != null).peek(x -> {
|
||||
x.setEntityId(null);
|
||||
});
|
||||
}
|
||||
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package eu.eudat.model.builder;
|
||||
|
||||
import eu.eudat.authorization.AuthorizationFlags;
|
||||
import eu.eudat.convention.ConventionService;
|
||||
import eu.eudat.data.EntityDoiEntity;
|
||||
import eu.eudat.model.*;
|
||||
import gr.cite.tools.data.builder.BuilderFactory;
|
||||
import gr.cite.tools.data.query.QueryFactory;
|
||||
import gr.cite.tools.exception.MyApplicationException;
|
||||
import gr.cite.tools.fieldset.FieldSet;
|
||||
import gr.cite.tools.logging.DataLogEntry;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class PublicEntityDoiBuilder extends BaseBuilder<PublicEntityDoi, EntityDoiEntity> {
|
||||
|
||||
private final QueryFactory queryFactory;
|
||||
|
||||
private final BuilderFactory builderFactory;
|
||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||
|
||||
@Autowired
|
||||
public PublicEntityDoiBuilder(
|
||||
ConventionService conventionService,
|
||||
QueryFactory queryFactory,
|
||||
BuilderFactory builderFactory) {
|
||||
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicEntityDoiBuilder.class)));
|
||||
this.queryFactory = queryFactory;
|
||||
this.builderFactory = builderFactory;
|
||||
}
|
||||
|
||||
public PublicEntityDoiBuilder authorize(EnumSet<AuthorizationFlags> values) {
|
||||
this.authorize = values;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PublicEntityDoi> build(FieldSet fields, List<EntityDoiEntity> data) throws MyApplicationException {
|
||||
this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0));
|
||||
this.logger.trace(new DataLogEntry("requested fields", fields));
|
||||
if (fields == null || data == null || fields.isEmpty())
|
||||
return new ArrayList<>();
|
||||
|
||||
List<PublicEntityDoi> models = new ArrayList<>();
|
||||
for (EntityDoiEntity d : data) {
|
||||
PublicEntityDoi m = new PublicEntityDoi();
|
||||
if (fields.hasField(this.asIndexer(PublicEntityDoi._id))) m.setId(d.getId());
|
||||
if (fields.hasField(this.asIndexer(PublicEntityDoi._entityType))) m.setEntityType(d.getEntityType());
|
||||
if (fields.hasField(this.asIndexer(PublicEntityDoi._repositoryId))) m.setRepositoryId(d.getRepositoryId());
|
||||
if (fields.hasField(this.asIndexer(PublicEntityDoi._doi))) m.setDoi(d.getDoi());
|
||||
if (fields.hasField(this.asIndexer(PublicEntityDoi._entityId))) m.setEntityId(d.getEntityId());
|
||||
|
||||
models.add(m);
|
||||
}
|
||||
|
||||
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
|
||||
|
||||
return models;
|
||||
}
|
||||
|
||||
}
|
|
@ -4,13 +4,13 @@ import eu.eudat.commons.validation.BaseValidator;
|
|||
import gr.cite.tools.validation.specification.Specification;
|
||||
import eu.eudat.convention.ConventionService;
|
||||
import eu.eudat.errorcode.ErrorThesaurusProperties;
|
||||
import org.apache.commons.compress.utils.Lists;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
@ -29,7 +29,7 @@ public class CloneDmpPersist {
|
|||
|
||||
public static final String _description = "description";
|
||||
|
||||
private List<UUID> descriptions = Lists.newArrayList();
|
||||
private List<UUID> descriptions = new ArrayList<>();
|
||||
|
||||
public static final String _descriptions = "descriptions";
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@ import gr.cite.tools.validation.specification.Specification;
|
|||
import eu.eudat.convention.ConventionService;
|
||||
import eu.eudat.data.DmpEntity;
|
||||
import eu.eudat.errorcode.ErrorThesaurusProperties;
|
||||
import org.apache.commons.compress.utils.Lists;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
@ -33,7 +33,7 @@ public class NewVersionDmpPersist {
|
|||
|
||||
public static final String _blueprintId = "blueprintId";
|
||||
|
||||
private List<UUID> descriptions = Lists.newArrayList();
|
||||
private List<UUID> descriptions = new ArrayList<>();
|
||||
|
||||
public static final String _descriptions = "descriptions";
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ import eu.eudat.data.*;
|
|||
import eu.eudat.errorcode.ErrorThesaurusProperties;
|
||||
import eu.eudat.event.DescriptionTouchedEvent;
|
||||
import eu.eudat.event.EventBroker;
|
||||
import eu.eudat.integrationevent.outbox.annotationentityremoval.AnnotationEntityRemovalIntegrationEventHandler;
|
||||
import eu.eudat.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
|
||||
import eu.eudat.integrationevent.outbox.descriptiontouched.DescriptionTouchedIntegrationEventHandler;
|
||||
import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEvent;
|
||||
import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
|
||||
|
@ -99,6 +101,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
private final StorageFileService storageFileService;
|
||||
private final DescriptionTouchedIntegrationEventHandler descriptionTouchedIntegrationEventHandler;
|
||||
private final AuthorizationContentResolver authorizationContentResolver;
|
||||
private final AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler;
|
||||
private final AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler;
|
||||
|
||||
@Autowired
|
||||
public DescriptionServiceImpl(
|
||||
|
@ -113,7 +117,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
QueryFactory queryFactory,
|
||||
JsonHandlingService jsonHandlingService,
|
||||
UserScope userScope,
|
||||
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, DescriptionTouchedIntegrationEventHandler descriptionTouchedIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver) {
|
||||
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, DescriptionTouchedIntegrationEventHandler descriptionTouchedIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler) {
|
||||
this.entityManager = entityManager;
|
||||
this.authorizationService = authorizationService;
|
||||
this.deleterFactory = deleterFactory;
|
||||
|
@ -135,6 +139,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
this.storageFileService = storageFileService;
|
||||
this.descriptionTouchedIntegrationEventHandler = descriptionTouchedIntegrationEventHandler;
|
||||
this.authorizationContentResolver = authorizationContentResolver;
|
||||
this.annotationEntityTouchedIntegrationEventHandler = annotationEntityTouchedIntegrationEventHandler;
|
||||
this.annotationEntityRemovalIntegrationEventHandler = annotationEntityRemovalIntegrationEventHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -230,6 +236,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
|
||||
this.descriptionTouchedIntegrationEventHandler.handle(DescriptionTouchedIntegrationEventHandler.buildEventFromPersistModel(model));
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDescription(data.getId());
|
||||
|
||||
this.elasticService.persistDescription(data);
|
||||
return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Description._id), data);
|
||||
}
|
||||
|
@ -294,71 +302,6 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
return event;
|
||||
}
|
||||
|
||||
// public List<eu.eudat.commons.types.descriptiontemplate.FieldEntity> getFieldById(String id){
|
||||
// List<eu.eudat.commons.types.descriptiontemplate.FieldEntity> fieldEntities = new ArrayList<>();
|
||||
// if (id == null || id.isBlank()) return fieldEntities;
|
||||
// if (this.getFieldSets() != null){
|
||||
// for (FieldSetEntity fieldSetEntity: this.getFieldSets()) {
|
||||
// fieldEntities.addAll(fieldSetEntity.getFieldById(id));
|
||||
// }
|
||||
// }
|
||||
// if (this.getSections() != null){
|
||||
// for (SectionEntity sectionEntity: this.getSections()) {
|
||||
// fieldEntities.addAll(sectionEntity.getFieldById(id));
|
||||
// }
|
||||
// }
|
||||
// return fieldEntities;
|
||||
// }
|
||||
|
||||
private void descriptionForce(DescriptionEntity description) throws Exception {
|
||||
List<String> datasetProfileValidators = new LinkedList<>();
|
||||
DescriptionTemplateEntity descriptionTemplateEntity = this.entityManager.find(DescriptionTemplateEntity.class, description.getDescriptionTemplateId());
|
||||
if (descriptionTemplateEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{description.getDescriptionTemplateId(), DescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
eu.eudat.commons.types.descriptiontemplate.DefinitionEntity descriptionTemplateDefinition = this.xmlHandlingService.fromXml(eu.eudat.commons.types.descriptiontemplate.DefinitionEntity.class, descriptionTemplateEntity.getDefinition());
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
|
||||
// DocumentBuilder builder = builderFactory.newDocumentBuilder();
|
||||
// Document xmlDocument = builder.parse(new ByteArrayInputStream(profile.getDefinition().getBytes()));
|
||||
//
|
||||
// XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
// String expression = "//validation/@type[.=1]/ancestor::field/@id";
|
||||
// NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
|
||||
//
|
||||
// for (int i = 0; i < nodeList.getLength(); i++) {
|
||||
// Node node = nodeList.item(i);
|
||||
// datasetProfileValidators.add(node.getNodeValue());
|
||||
// }
|
||||
//
|
||||
// expression = "//validation/@type[.=1]/ancestor::fieldSet";
|
||||
// nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
|
||||
//
|
||||
//
|
||||
// JSONObject obj = new JSONObject(description.getProperties());
|
||||
// VisibilityRuleService visibilityRuleService = new VisibilityRuleServiceImpl();
|
||||
// visibilityRuleService.setProperties(obj.toMap());
|
||||
//
|
||||
// description.setProfile(profile);
|
||||
// PagedDatasetProfile pagedDatasetProfile = this.getPagedProfile(new DatasetWizardModel(), description);
|
||||
// visibilityRuleService.buildVisibilityContext(pagedDatasetProfile.getRules());
|
||||
//
|
||||
//
|
||||
// String failedField = null;
|
||||
//
|
||||
// for (String validator : datasetProfileValidators) {
|
||||
// if (obj.has(validator) && isNullOrEmpty(obj.getString(validator)) && isElementVisible(nodeList, validator, visibilityRuleService)) {
|
||||
// //throw new Exception("Field value of " + validator + " must be filled.");
|
||||
// failedField = validator;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return failedField;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Description persistStatus(DescriptionStatusPersist model, FieldSet fields) throws IOException {
|
||||
logger.debug(new MapLogEntry("persisting data dmp").And("model", model).And("fields", fields));
|
||||
|
@ -385,6 +328,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
|
||||
this.elasticService.persistDescription(data);
|
||||
this.eventBroker.emit(new DescriptionTouchedEvent(data.getId()));
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDescription(data.getId());
|
||||
}
|
||||
return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Description._id), data);
|
||||
}
|
||||
|
@ -706,6 +651,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(id)), Permission.DeleteDescription);
|
||||
|
||||
this.deleterFactory.deleter(DescriptionDeleter.class).deleteAndSaveByIds(List.of(id), false);
|
||||
|
||||
this.annotationEntityRemovalIntegrationEventHandler.handleDescription(id);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
@ -774,6 +721,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
|
||||
this.elasticService.persistDescription(newDescription);
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDescription(newDescription.getId());
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDescription(existing.getId());
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
|
|
@ -24,6 +24,7 @@ import eu.eudat.data.*;
|
|||
import eu.eudat.errorcode.ErrorThesaurusProperties;
|
||||
import eu.eudat.event.DmpTouchedEvent;
|
||||
import eu.eudat.event.EventBroker;
|
||||
import eu.eudat.integrationevent.outbox.annotationentityremoval.AnnotationEntityRemovalIntegrationEventHandler;
|
||||
import eu.eudat.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
|
||||
import eu.eudat.integrationevent.outbox.dmptouched.DmpTouchedIntegrationEventHandler;
|
||||
import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEvent;
|
||||
|
@ -124,6 +125,7 @@ public class DmpServiceImpl implements DmpService {
|
|||
private final DmpTouchedIntegrationEventHandler dmpTouchedIntegrationEventHandler;
|
||||
|
||||
private final AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler;
|
||||
private final AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler;
|
||||
private final AuthorizationContentResolver authorizationContentResolver;
|
||||
|
||||
@Autowired
|
||||
|
@ -148,7 +150,7 @@ public class DmpServiceImpl implements DmpService {
|
|||
ValidatorFactory validatorFactory,
|
||||
ElasticService elasticService,
|
||||
DmpTouchedIntegrationEventHandler dmpTouchedIntegrationEventHandler,
|
||||
AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver) {
|
||||
AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver) {
|
||||
this.entityManager = entityManager;
|
||||
this.authorizationService = authorizationService;
|
||||
this.deleterFactory = deleterFactory;
|
||||
|
@ -170,6 +172,7 @@ public class DmpServiceImpl implements DmpService {
|
|||
this.elasticService = elasticService;
|
||||
this.dmpTouchedIntegrationEventHandler = dmpTouchedIntegrationEventHandler;
|
||||
this.annotationEntityTouchedIntegrationEventHandler = annotationEntityTouchedIntegrationEventHandler;
|
||||
this.annotationEntityRemovalIntegrationEventHandler = annotationEntityRemovalIntegrationEventHandler;
|
||||
this.authorizationContentResolver = authorizationContentResolver;
|
||||
}
|
||||
|
||||
|
@ -202,13 +205,13 @@ public class DmpServiceImpl implements DmpService {
|
|||
|
||||
this.dmpTouchedIntegrationEventHandler.handle(DmpTouchedIntegrationEventHandler.buildEventFromPersistModel(model));
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handle(AnnotationEntityTouchedIntegrationEventHandler.buildEventFromPersistModel(model));
|
||||
|
||||
this.sendNotification(data);
|
||||
this.assignUsers(data.getId(), this.inviteUserOrAssignUsers(data.getId(), model.getUsers(), false), null, false);
|
||||
|
||||
this.elasticService.persistDmp(data);
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(data.getId());
|
||||
|
||||
return this.builderFactory.builder(DmpBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Dmp._id, Dmp._hash), data);
|
||||
}
|
||||
|
||||
|
@ -334,6 +337,8 @@ public class DmpServiceImpl implements DmpService {
|
|||
|
||||
this.deleterFactory.deleter(DmpDeleter.class).deleteAndSaveByIds(List.of(id), false);
|
||||
if (previousFinalized != null) this.elasticService.persistDmp(previousFinalized);
|
||||
|
||||
this.annotationEntityRemovalIntegrationEventHandler.handleDmp(data.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -445,6 +450,9 @@ public class DmpServiceImpl implements DmpService {
|
|||
this.elasticService.persistDmp(oldDmpEntity);
|
||||
this.elasticService.persistDmp(newDmp);
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(newDmp.getId());
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(oldDmpEntity.getId());
|
||||
|
||||
return this.builderFactory.builder(DmpBuilder.class).build(BaseFieldSet.build(fields, Dmp._id), newDmp);
|
||||
}
|
||||
|
||||
|
@ -565,9 +573,10 @@ public class DmpServiceImpl implements DmpService {
|
|||
|
||||
this.entityManager.flush();
|
||||
|
||||
|
||||
this.elasticService.persistDmp(newDmp);
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(newDmp.getId());
|
||||
|
||||
DmpEntity resultingDmpEntity = this.queryFactory.query(DmpQuery.class).ids(newDmp.getId()).firstAs(fields);
|
||||
return this.builderFactory.builder(DmpBuilder.class).build(fields, resultingDmpEntity);
|
||||
}
|
||||
|
@ -615,6 +624,9 @@ public class DmpServiceImpl implements DmpService {
|
|||
.collect();
|
||||
|
||||
this.elasticService.persistDmp(dmpEntity);
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(dmpEntity.getId());
|
||||
|
||||
return this.builderFactory.builder(DmpUserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fieldSet, DmpUser._id, DmpUser._hash), persisted);
|
||||
}
|
||||
|
||||
|
@ -636,6 +648,8 @@ public class DmpServiceImpl implements DmpService {
|
|||
if (dmpEntity == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{model.getDmpId(), Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
this.elasticService.persistDmp(dmpEntity);
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(dmpEntity.getId());
|
||||
|
||||
return this.builderFactory.builder(DmpBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Dmp._id, Dmp._hash), data);
|
||||
}
|
||||
|
||||
|
@ -727,8 +741,6 @@ public class DmpServiceImpl implements DmpService {
|
|||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private @NotNull DmpBlueprintValueEntity buildDmpBlueprintValueEntity(DmpBlueprintValuePersist persist){
|
||||
DmpBlueprintValueEntity data = new DmpBlueprintValueEntity();
|
||||
if (persist == null) return data;
|
||||
|
@ -738,8 +750,6 @@ public class DmpServiceImpl implements DmpService {
|
|||
return data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private @NotNull List<DmpReferencePersist> buildDmpReferencePersists(DmpPropertiesPersist persist){
|
||||
List<DmpReferencePersist> dmpReferencePersists = new ArrayList<>();
|
||||
if (persist.getDmpBlueprintValues() != null && !persist.getDmpBlueprintValues().isEmpty()){
|
||||
|
@ -839,7 +849,6 @@ public class DmpServiceImpl implements DmpService {
|
|||
this.entityManager.flush();
|
||||
}
|
||||
|
||||
|
||||
private void patchAndSaveTemplates(UUID id, List<DmpDescriptionTemplatePersist> models) throws InvalidApplicationException {
|
||||
if (models == null) models = new ArrayList<>();
|
||||
List<DmpDescriptionTemplateEntity> items = this.queryFactory.query(DmpDescriptionTemplateQuery.class).isActive(IsActive.Active).dmpIds(id).collect();
|
||||
|
@ -942,6 +951,8 @@ public class DmpServiceImpl implements DmpService {
|
|||
this.entityManager.flush();
|
||||
|
||||
this.elasticService.persistDmp(dmp);
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(dmp.getId());
|
||||
this.sendNotification(dmp);
|
||||
}
|
||||
|
||||
|
@ -964,12 +975,16 @@ public class DmpServiceImpl implements DmpService {
|
|||
|
||||
this.updateVersionStatusAndSave(dmp, DmpStatus.Finalized, dmp.getStatus());
|
||||
this.entityManager.flush();
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(dmp.getId());
|
||||
this.sendNotification(dmp);
|
||||
}
|
||||
|
||||
// invites
|
||||
public void inviteUserOrAssignUsers(UUID id, List<DmpUserPersist> users) throws InvalidApplicationException, JAXBException, IOException {
|
||||
this.inviteUserOrAssignUsers(id, users, true);
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1074,7 +1089,6 @@ public class DmpServiceImpl implements DmpService {
|
|||
return persist.getToken();
|
||||
}
|
||||
|
||||
|
||||
public void dmpInvitationAccept(String token) {
|
||||
ActionConfirmationEntity action = this.queryFactory.query(ActionConfirmationQuery.class).tokens(token).types(ActionConfirmationType.DmpInvitation).isActive(IsActive.Active).first();
|
||||
|
||||
|
@ -1102,6 +1116,8 @@ public class DmpServiceImpl implements DmpService {
|
|||
|
||||
action.setStatus(ActionConfirmationStatus.Accepted);
|
||||
this.entityManager.merge(action);
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(dmpInvitation.getDmpId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<version>3.2.1</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@ -41,7 +41,7 @@
|
|||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20230227</version>
|
||||
<version>20240303</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
|
@ -92,7 +92,7 @@
|
|||
<dependency>
|
||||
<groupId>org.elasticsearch.client</groupId>
|
||||
<artifactId>elasticsearch-rest-high-level-client</artifactId>
|
||||
<version>7.6.0</version>
|
||||
<version>7.17.19</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.orm</groupId>
|
||||
|
@ -109,7 +109,7 @@
|
|||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<version>2.4.0</version>
|
||||
<version>2.9.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
@ -153,24 +153,8 @@
|
|||
<version>3.5</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.xmlgraphics/fop -->
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>fop</artifactId>
|
||||
<version>2.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
|
@ -190,11 +174,6 @@
|
|||
<version>1.0.6</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.itext.extension -->
|
||||
<dependency>
|
||||
<groupId>fr.opensagres.xdocreport</groupId>
|
||||
<artifactId>fr.opensagres.xdocreport.itext.extension</artifactId>
|
||||
<version>2.0.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
|
@ -356,18 +335,18 @@
|
|||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
<artifactId>queue-inbox</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>2.1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
<artifactId>queue-outbox</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>2.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>gr.cite</groupId>
|
||||
<artifactId>rabbitmq-core</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>2.1.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
|
|
@ -16,7 +16,7 @@ spring:
|
|||
dialect: org.hibernate.dialect.PostgreSQLDialect
|
||||
hibernate:
|
||||
naming:
|
||||
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
|
||||
physical-strategy: eu.eudat.configurations.db.PrefixPhysicalNamingStrategy
|
||||
implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
|
||||
datasource:
|
||||
url: ${DB_URL:}
|
||||
|
@ -29,3 +29,6 @@ spring:
|
|||
maximum-pool-size: 10
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 1800000
|
||||
|
||||
naming-strategy:
|
||||
prefix:
|
|
@ -35,7 +35,8 @@ queue:
|
|||
user-removal-topic: user.remove
|
||||
dmp-touch-topic: dmp.touch
|
||||
description-touch-topic: description.touch
|
||||
annotation-entity-touch-topic: annotation.entity.touch
|
||||
annotation-entities-touch-topic: annotation.entities.touch
|
||||
annotation-entities-removal-topic: annotation.entities.remove
|
||||
what-you-know-about-me-completed-topic: whatyouknowaboutme.completed
|
||||
generate-file-topic: generate.file
|
||||
rabbitmq:
|
||||
|
|
|
@ -10,7 +10,7 @@ BEGIN
|
|||
exchange character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
route character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
message_id uuid NOT NULL,
|
||||
notify_status character varying(100) COLLATE pg_catalog."default" NOT NULL,
|
||||
notify_status smallint NOT NULL,
|
||||
retry_count integer NOT NULL,
|
||||
published_at timestamp without time zone,
|
||||
confirmed_at timestamp without time zone,
|
||||
|
|
|
@ -7,14 +7,14 @@ BEGIN
|
|||
CREATE TABLE public."QueueInbox"
|
||||
(
|
||||
id uuid NOT NULL,
|
||||
queue character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
exchange character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
route character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
queue character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
exchange character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
route character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
application_id character varying(100) COLLATE pg_catalog."default" NOT NULL,
|
||||
message_id uuid NOT NULL,
|
||||
message json NOT NULL,
|
||||
retry_count integer,
|
||||
status character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
status smallint NOT NULL,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
tenant uuid,
|
||||
|
|
|
@ -7,14 +7,14 @@ BEGIN
|
|||
CREATE TABLE public."ntf_QueueInbox"
|
||||
(
|
||||
id uuid NOT NULL,
|
||||
queue character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
exchange character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
route character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
queue character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
exchange character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
route character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
application_id character varying(100) COLLATE pg_catalog."default" NOT NULL,
|
||||
message_id uuid NOT NULL,
|
||||
message json NOT NULL,
|
||||
retry_count integer,
|
||||
status character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
status smallint NOT NULL,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
tenant uuid,
|
||||
|
|
|
@ -10,7 +10,7 @@ BEGIN
|
|||
exchange character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
route character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
message_id uuid NOT NULL,
|
||||
notify_status character varying(100) COLLATE pg_catalog."default" NOT NULL,
|
||||
notify_status smallint NOT NULL,
|
||||
retry_count integer NOT NULL,
|
||||
published_at timestamp without time zone,
|
||||
confirmed_at timestamp without time zone,
|
||||
|
|
|
@ -7,14 +7,14 @@ BEGIN
|
|||
CREATE TABLE public."ant_QueueInbox"
|
||||
(
|
||||
id uuid NOT NULL,
|
||||
queue character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
exchange character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
route character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
queue character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
exchange character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
route character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
application_id character varying(100) COLLATE pg_catalog."default" NOT NULL,
|
||||
message_id uuid NOT NULL,
|
||||
message json NOT NULL,
|
||||
retry_count integer,
|
||||
status character varying(50) COLLATE pg_catalog."default" NOT NULL,
|
||||
status smallint NOT NULL,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
tenant uuid,
|
||||
|
|
|
@ -10,7 +10,7 @@ BEGIN
|
|||
exchange character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
route character varying(200) COLLATE pg_catalog."default" NOT NULL,
|
||||
message_id uuid NOT NULL,
|
||||
notify_status character varying(100) COLLATE pg_catalog."default" NOT NULL,
|
||||
notify_status smallint NOT NULL,
|
||||
retry_count integer NOT NULL,
|
||||
published_at timestamp without time zone,
|
||||
confirmed_at timestamp without time zone,
|
||||
|
|
|
@ -47,6 +47,7 @@ import { InAppNotificationService } from './services/inapp-notification/inapp-no
|
|||
import { NotificationService } from './services/notification/notification-service';
|
||||
import { SemanticsService } from './services/semantic/semantics.service';
|
||||
import { PrefillingSourceService } from './services/prefilling-source/prefilling-source.service';
|
||||
import { VisibilityRulesService } from '@app/ui/description/editor/description-form/visibility-rules/visibility-rules.service';
|
||||
//
|
||||
//
|
||||
// This is shared module that provides all the services. Its imported only once on the AppModule.
|
||||
|
@ -112,7 +113,8 @@ export class CoreServiceModule {
|
|||
InAppNotificationService,
|
||||
NotificationService,
|
||||
SemanticsService,
|
||||
PrefillingSourceService
|
||||
PrefillingSourceService,
|
||||
VisibilityRulesService
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import { DmpAssociatedUser, User } from "../user/user";
|
|||
import { DmpReference } from './dmp-reference';
|
||||
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
||||
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
||||
import { EntityType } from '@app/core/common/enum/entity-type';
|
||||
|
||||
export interface Dmp extends BaseEntity {
|
||||
label?: string;
|
||||
|
@ -166,6 +167,7 @@ export interface PublicDmp extends BaseEntity {
|
|||
dmpReferences: PublicDmpReference[];
|
||||
dmpUsers: PublicDmpUser[];
|
||||
descriptions: PublicDescription[];
|
||||
entityDois: PublicEntityDoi[];
|
||||
}
|
||||
|
||||
export interface PublicDmpReference {
|
||||
|
@ -201,3 +203,10 @@ export interface PublicUser {
|
|||
name: string;
|
||||
}
|
||||
|
||||
export interface PublicEntityDoi {
|
||||
id: Guid;
|
||||
entityType: EntityType;
|
||||
entityId: Guid;
|
||||
repositoryId: string;
|
||||
doi: string;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<div class="row" *ngFor="let ruleFormGroup of form['controls'] let i=index;" [formGroup]="ruleFormGroup">
|
||||
<span class="col-auto align-self-center">{{i + 1}}</span>
|
||||
|
||||
<app-description-template-editor-default-value-component class="col align-self-center" [fieldType]="fieldTypeForCheck" [form]="ruleFormGroup.get('value')" [formArrayOptions]="formArrayOptionsForCheck" placeHolder="{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.RULE.FIELDS.RULE-IF'| translate}}" required="true"></app-description-template-editor-default-value-component>
|
||||
<app-description-template-editor-default-value-component *ngIf="isTextType(fieldTypeForCheck)" class="col align-self-center" [fieldType]="fieldTypeForCheck" [form]="ruleFormGroup.get('textValue')" [formArrayOptions]="formArrayOptionsForCheck" placeHolder="{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.RULE.FIELDS.RULE-IF'| translate}}" required="true"></app-description-template-editor-default-value-component>
|
||||
<app-description-template-editor-default-value-component *ngIf="isDateType(fieldTypeForCheck)" class="col align-self-center" [fieldType]="fieldTypeForCheck" [form]="ruleFormGroup.get('dateValue')" [formArrayOptions]="formArrayOptionsForCheck" placeHolder="{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.RULE.FIELDS.RULE-IF'| translate}}" required="true"></app-description-template-editor-default-value-component>
|
||||
|
||||
<!-- SELECTION -->
|
||||
<mat-form-field class="col align-self-center">
|
||||
|
|
|
@ -39,6 +39,30 @@ export class DescriptionTemplateEditorRuleComponent implements OnInit {
|
|||
|
||||
}
|
||||
|
||||
isTextType(type: DescriptionTemplateFieldType){
|
||||
return type == DescriptionTemplateFieldType.FREE_TEXT || type == DescriptionTemplateFieldType.CHECK_BOX ||
|
||||
type == DescriptionTemplateFieldType.TEXT_AREA || type == DescriptionTemplateFieldType.RICH_TEXT_AREA ||
|
||||
type == DescriptionTemplateFieldType.BOOLEAN_DECISION || type == DescriptionTemplateFieldType.RADIO_BOX ||
|
||||
type == DescriptionTemplateFieldType.CURRENCY || type == DescriptionTemplateFieldType.SELECT;
|
||||
}
|
||||
|
||||
isTextListType(type: DescriptionTemplateFieldType){
|
||||
return type == DescriptionTemplateFieldType.TAGS || type == DescriptionTemplateFieldType.INTERNAL_ENTRIES_DMPS ||
|
||||
type == DescriptionTemplateFieldType.INTERNAL_ENTRIES_DESCRIPTIONS;
|
||||
}
|
||||
|
||||
isDateType(type: DescriptionTemplateFieldType){
|
||||
return type == DescriptionTemplateFieldType.DATE_PICKER;
|
||||
}
|
||||
|
||||
isReferenceType(type: DescriptionTemplateFieldType){
|
||||
return type == DescriptionTemplateFieldType.REFERENCE_TYPES;
|
||||
}
|
||||
|
||||
isExternalIdentifierType(type: DescriptionTemplateFieldType){
|
||||
return type == DescriptionTemplateFieldType.VALIDATION || type == DescriptionTemplateFieldType.DATASET_IDENTIFIER;;
|
||||
}
|
||||
|
||||
targetValidation() {
|
||||
//TODO
|
||||
}
|
||||
|
|
|
@ -139,9 +139,9 @@
|
|||
<!-- <mat-form-field>
|
||||
<input matInput #email placeholder="{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-USERS'| translate}}" (focus)="onUserFieldFocus()" (blur)="onUserFieldBlur()" (keyup.enter)="addUser(email)">
|
||||
</mat-form-field> -->
|
||||
<mat-form-field class="full-width basic-info-input">
|
||||
<mat-form-field class="full-width basic-info-input" *ngIf="!formGroup.disabled">
|
||||
<mat-label>{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-USERS' | translate}}</mat-label>
|
||||
<app-single-auto-complete [disabled]="formGroup.disabled" [required]="false" [formControl]="userFormControl" (optionSelected)="addUser($event)" placeholder="{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-USERS' | translate}}" [configuration]="userService.singleAutocompleteConfiguration">
|
||||
<app-single-auto-complete [required]="false" [formControl]="userFormControl" (optionSelected)="addUser($event)" placeholder="{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-USERS' | translate}}" [configuration]="userService.singleAutocompleteConfiguration">
|
||||
</app-single-auto-complete>
|
||||
<mat-error *ngIf="formGroup.get('type').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</mat-form-field>
|
||||
|
|
|
@ -951,7 +951,7 @@ export class DescriptionTemplateRuleEditorModel implements DescriptionTemplateRu
|
|||
validationErrorModel
|
||||
});
|
||||
|
||||
['target', 'value'].forEach(keyField => {
|
||||
['target', 'textValue', 'textListValue', 'dateValue'].forEach(keyField => {
|
||||
const control = formGroup?.get(keyField);
|
||||
control?.clearValidators();
|
||||
control?.addValidators(context.getValidation(keyField).validators);
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
</div>
|
||||
<div *ngIf="!fieldSet?.multiplicity?.tableView" class="col-12">
|
||||
<div class="row" *ngFor="let fieldSetItemPropertiesControl of propertiesFormGroup?.get('items')?.controls">
|
||||
<div class="col" *ngIf="visibilityRulesService.isVisibleMap[fieldSet.id + '_' + fieldSetItemPropertiesControl.get('ordinal').value]">
|
||||
<div class="col" *ngIf="visibilityRulesService && visibilityRulesService.isVisibleMap[fieldSet.id + '_' + fieldSetItemPropertiesControl.get('ordinal').value]">
|
||||
<div class="row">
|
||||
<div *ngFor="let field of fieldSet.fields; let i = index;" class="col-12 compositeField">
|
||||
<ng-container *ngIf="visibilityRulesService.isVisibleMap[field.id + '_' + fieldSetItemPropertiesControl.get('ordinal').value]">
|
||||
<ng-container *ngIf="visibilityRulesService && visibilityRulesService.isVisibleMap[field.id + '_' + fieldSetItemPropertiesControl.get('ordinal').value]">
|
||||
<div class="row">
|
||||
<h5 *ngIf="placeholderTitle" class="col-auto font-weight-bold">{{field.label}}</h5>
|
||||
</div>
|
||||
|
@ -48,9 +48,9 @@
|
|||
<th class="actions"></th>
|
||||
</tr>
|
||||
<ng-container *ngFor="let fieldSetItemPropertiesControl of propertiesFormGroup?.get('items')?.controls; let j = index">
|
||||
<tr *ngIf="visibilityRulesService.isVisibleMap[fieldSet.id + '_' + fieldSetItemPropertiesControl.get('ordinal').value]">
|
||||
<tr *ngIf="visibilityRulesService && visibilityRulesService.isVisibleMap[fieldSet.id + '_' + fieldSetItemPropertiesControl.get('ordinal').value]">
|
||||
<td *ngFor="let field of fieldSet.fields;" class="text-wrap">
|
||||
<ng-container *ngIf="visibilityRulesService.isVisibleMap[field.id + '_' + fieldSetItemPropertiesControl.get('ordinal').value]">
|
||||
<ng-container *ngIf="visibilityRulesService && visibilityRulesService.isVisibleMap[field.id + '_' + fieldSetItemPropertiesControl.get('ordinal').value]">
|
||||
{{fieldSetItemPropertiesControl.get('fields').get(field.id).get('value').getRawValue()}}
|
||||
</ng-container>
|
||||
</td>
|
||||
|
|
|
@ -1,456 +0,0 @@
|
|||
// import { ApplicationRef, Injectable, NgZone } from '@angular/core';
|
||||
// import { AbstractControl, UntypedFormArray, UntypedFormGroup } from '@angular/forms';
|
||||
// import { isNumeric } from '@app/utilities/enhancers/utils';
|
||||
// import { Observable, Subject } from 'rxjs';
|
||||
// import { VisibilityRule } from './models/visibility-rule';
|
||||
// import { VisibilityRuleSource } from './models/visibility-rule-source';
|
||||
// import { VisibilityRulesContext } from './models/visibility-rules-context';
|
||||
// import { DescriptionTemplate, DescriptionTemplatePage, DescriptionTemplateSection } from '@app/core/model/description-template/description-template';
|
||||
// import { Rule } from './models/rule';
|
||||
|
||||
// @Injectable()
|
||||
// export class VisibilityRulesService {
|
||||
|
||||
// private readonly VISIBILITY_RULE_LOGIC: 'OR' | 'AND' = 'OR';
|
||||
// private readonly DEFAULTVISIBILITY = false;
|
||||
|
||||
// private visibilityRuleContext: VisibilityRulesContext;
|
||||
// private form: AbstractControl;
|
||||
|
||||
// public isVisibleMap: { [key: string]: boolean } = {};
|
||||
|
||||
// private elementVisibilityMapSubject = new Subject<{ [key: string]: boolean }>();
|
||||
// private elementComputationalMap = new Map<String, Map<String, boolean>>(); /// keep saved the values of each form control validity value
|
||||
// private _changeMade$ = new Subject<void>();
|
||||
|
||||
|
||||
// // get isVisibleMap(): MapWithDefault {
|
||||
// // // console.log('isVisibleMap');
|
||||
// // return this.elementVisibilityMap;
|
||||
|
||||
// // }; /// keep saved the values of each form control validity value
|
||||
|
||||
// constructor(
|
||||
// public applicationReference: ApplicationRef,
|
||||
// public ngZone: NgZone
|
||||
// ) {
|
||||
|
||||
// }
|
||||
|
||||
// getElementVisibilityMapObservable(): Observable<{ [key: string]: boolean }> {
|
||||
// // this.isVisibleMap
|
||||
// // console.log('getElementVisibilityMapObservable: ');
|
||||
// return this.elementVisibilityMapSubject.asObservable();
|
||||
// }
|
||||
|
||||
// public checkElementVisibility(id: string): boolean {
|
||||
// //console.log('checkElementVisibility: ' + id);
|
||||
// return true;
|
||||
// // if (this.visibilityRuleContext.rules.filter(item => item.targetControlId === id).length === 0) { return true; }
|
||||
// // console.log(this.elementVisibilityMap.has(id) ? this.elementVisibilityMap.get(id) : false);
|
||||
// // return this.elementVisibilityMap.has(id) ? this.elementVisibilityMap.get(id) : false;
|
||||
// }
|
||||
|
||||
// public buildVisibilityRules(item: Array<Rule>, form: AbstractControl) {
|
||||
// this.visibilityRuleContext = new VisibilityRulesContext();
|
||||
// this.visibilityRuleContext.buildVisibilityRuleContext(item || []);
|
||||
// this.form = form;
|
||||
// this.resetVisibilityRules();
|
||||
// }
|
||||
|
||||
// public updateValueAndVisibility(id: string, value: any) {
|
||||
// //console.log('updateValueAndVisibility: ' + id + ' value: ' + value);
|
||||
// const visibilityRules = this.visibilityRuleContext.rules.filter(item => item.sourceVisibilityRules.filter(source => source.sourceControlId === id).length > 0);
|
||||
// if (visibilityRules.length > 0) {
|
||||
// visibilityRules.forEach(item => this.evaluateVisibility(item, value, id));
|
||||
// this.elementVisibilityMapSubject.next(this.isVisibleMap);
|
||||
// }
|
||||
// }
|
||||
|
||||
// private evaluateVisibility(visibilityRule: VisibilityRule, value: any, sourceId: string) {// source controlId is the same
|
||||
// //console.log('evaluateVisibility: ' + visibilityRule + ' value: ' + value + ' sourceId: ' + sourceId);
|
||||
|
||||
// const targetId = visibilityRule.targetControlId;
|
||||
// const visibilityMap = this.elementComputationalMap.get(targetId) ? this.elementComputationalMap.get(targetId) : new Map<String, boolean>();
|
||||
|
||||
|
||||
// if (value instanceof Array) {
|
||||
|
||||
// const parsedSourceControlValues = visibilityRule.sourceVisibilityRules.map(e => this.parseValue(e.sourceControlValue));
|
||||
// const parsedValues = value.map(e => this.parseValue(e));
|
||||
|
||||
// const isVisible = parsedValues.map(v => parsedSourceControlValues.includes(v)).reduce((acc, current) => acc || current, false);
|
||||
|
||||
|
||||
// // if(isVisible){
|
||||
// // this._emitChangesIfNeeded(visibilityRule.targetControlId, true);
|
||||
// // this.elementVisibilityMap.set(visibilityRule.targetControlId, true);
|
||||
// // return;
|
||||
// // }
|
||||
// visibilityMap.set(sourceId, isVisible);
|
||||
|
||||
// } else {
|
||||
// const visibilityDependencySource = visibilityRule.sourceVisibilityRules.filter(x => x.sourceControlId === sourceId);
|
||||
|
||||
// const shouldBeVisible = visibilityDependencySource.reduce((isVisible, x) => {
|
||||
|
||||
// const shouldBeHidden = value !== null && (this.parseValue(value) !== this.parseValue(x.sourceControlValue));
|
||||
// return this.VISIBILITY_RULE_LOGIC === 'OR' ? (isVisible || !shouldBeHidden) : (isVisible && !shouldBeHidden);
|
||||
// // if(value !== null && )
|
||||
// }, this.VISIBILITY_RULE_LOGIC === 'AND');
|
||||
// visibilityMap.set(sourceId, shouldBeVisible);
|
||||
// }
|
||||
|
||||
|
||||
// this.elementComputationalMap.set(targetId, visibilityMap);// unnessecary
|
||||
|
||||
|
||||
// const isVisible = this._computeVisibility(targetId);
|
||||
// this._emitChangesIfNeeded(targetId, isVisible);
|
||||
// const previousVisibility = this.isVisibleMap[targetId];
|
||||
// this.isVisibleMap[targetId] = isVisible;
|
||||
|
||||
// if (!isVisible && previousVisibility !== isVisible) {
|
||||
// this.resetControlWithId(this.form, targetId);
|
||||
// }
|
||||
|
||||
|
||||
// // for (let i = 0; i < visibilityRule.sourceVisibilityRules.length; i++) {
|
||||
// // if (value != null && (this.parseValue(value) !== this.parseValue(visibilityRule.sourceVisibilityRules[i].sourceControlValue))) {
|
||||
// // this._emitChangesIfNeeded(visibilityRule.targetControlId, false);
|
||||
// // this.elementVisibilityMap.set(visibilityRule.targetControlId, false);
|
||||
// // this.resetControlWithId(this.form, visibilityRule.targetControlId);
|
||||
// // //this.updateValueAndVisibility(visibilityRule.targetControlId, null);
|
||||
// // // this.clearValues(targetPathKey);
|
||||
// // return;
|
||||
// // }
|
||||
// // }
|
||||
// // this._emitChangesIfNeeded(visibilityRule.targetControlId, true);
|
||||
// // this.elementVisibilityMap.set(visibilityRule.targetControlId, true);
|
||||
|
||||
// // this.updateValueAndVisibility(visibilityRule.targetControlId, null);
|
||||
// }
|
||||
|
||||
|
||||
// private _computeVisibility(targetId: string): boolean {
|
||||
// //console.log('_computeVisibility: ' + targetId);
|
||||
|
||||
// const visibilityMap = this.elementComputationalMap.get(targetId);
|
||||
// const values = visibilityMap.values();
|
||||
// let currentVal = values.next();
|
||||
// let visibilityValues: boolean[] = [];
|
||||
// while (!currentVal.done) {
|
||||
// visibilityValues.push(currentVal.value);
|
||||
// currentVal = values.next();
|
||||
// }
|
||||
|
||||
|
||||
// if (visibilityValues.length) {
|
||||
// return visibilityValues.reduce((r, c) => {
|
||||
// if (this.VISIBILITY_RULE_LOGIC === 'OR') {
|
||||
// return r || c;
|
||||
// } else {
|
||||
// return r && c;
|
||||
// }
|
||||
// }, visibilityValues[0]);
|
||||
// }
|
||||
|
||||
// return this.DEFAULTVISIBILITY;
|
||||
// }
|
||||
|
||||
// private resetVisibilityRules() {
|
||||
// //console.log('resetVisibilityRules: ');
|
||||
|
||||
// this.isVisibleMap = {};
|
||||
// this.elementComputationalMap.clear();
|
||||
// this.elementComputationalMap = new Map<String, Map<String, boolean>>();
|
||||
// this._populateComputationMap(); /// !IMPORTANT FOR THE AND LOGIC
|
||||
// this._changeMade$.next();
|
||||
// }
|
||||
|
||||
// private _populateComputationMap(): void {
|
||||
// //console.log('_populateComputationMap: ');
|
||||
// // this.visibilityRuleContext.rules.forEach(rule => {
|
||||
// // const targetId = rule.targetControlId;
|
||||
// // const visibilityMap = this.elementComputationalMap.get(targetId) ? this.elementComputationalMap.get(targetId) : new Map<String, boolean>();
|
||||
// // rule.sourceVisibilityRules.forEach(vr => {
|
||||
// // visibilityMap.set(vr.sourceControlId, this.DEFAULTVISIBILITY);
|
||||
// // });
|
||||
// // this.elementComputationalMap.set(targetId, visibilityMap);
|
||||
// // });
|
||||
// }
|
||||
|
||||
// parseValue(value: any) {
|
||||
// if (typeof value === 'string') {
|
||||
// if (isNumeric(value)) { return value; }
|
||||
// else if (value === 'true') {
|
||||
// return true;
|
||||
// }
|
||||
// else if (value === 'false') {
|
||||
// return false;
|
||||
// }
|
||||
// else { return this.translate(value); }
|
||||
// } else { return value; }
|
||||
// }
|
||||
|
||||
// search(path, obj, target) {
|
||||
// for (const k in obj) {
|
||||
// if (obj.hasOwnProperty(k)) {
|
||||
// if (obj[k] === target) {
|
||||
// return path + '.' + k;
|
||||
// } else if (typeof obj[k] === 'object') {
|
||||
// const result = this.search(path + '.' + k, obj[k], target);
|
||||
// if (result) {
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// scanIfChildsOfCompositeFieldHasVisibleItems(compositeFieldParent: UntypedFormGroup): boolean {
|
||||
// // console.log('scanIfChildsOfCompositeFieldHasVisibleItems: ' + compositeFieldParent);
|
||||
|
||||
// //TODO: implement this
|
||||
// return true;
|
||||
// // let isVisible = false;
|
||||
// // (<UntypedFormArray>(compositeFieldParent.get('fields'))).controls.forEach(element => {
|
||||
// // if (this.checkElementVisibility(element.get('id').value)) {
|
||||
// // isVisible = true;
|
||||
// // }
|
||||
// // });
|
||||
// // return isVisible;
|
||||
// }
|
||||
|
||||
// private translate(item: any) {
|
||||
// try {
|
||||
// return JSON.parse(item).value;
|
||||
// } catch (error) {
|
||||
// return item;
|
||||
// }
|
||||
// }
|
||||
|
||||
// private resetControlWithId(formControl: AbstractControl, id: string) {
|
||||
// //'resetControlWithId: ' + id);
|
||||
// //TODO: implement this
|
||||
// // if (formControl instanceof UntypedFormGroup) {
|
||||
// // if ((formControl as UntypedFormGroup).contains('id') && (formControl as UntypedFormGroup).contains('value') && (formControl as UntypedFormGroup).get('id').value === id) {
|
||||
// // this.resetFieldFormGroup(formControl);
|
||||
// // } if ((formControl as UntypedFormGroup).contains('id') && (formControl as UntypedFormGroup).contains('fields') && (formControl as UntypedFormGroup).get('id').value === id) {
|
||||
// // this.resetCompositeFieldFormGroup(formControl);
|
||||
// // } else {
|
||||
// // Object.keys(formControl.controls).forEach(item => {
|
||||
// // const control = formControl.get(item);
|
||||
// // this.resetControlWithId(control, id);
|
||||
// // });
|
||||
// // }
|
||||
// // } else if (formControl instanceof UntypedFormArray) {
|
||||
// // formControl.controls.forEach(item => {
|
||||
// // this.resetControlWithId(item, id);
|
||||
// // });
|
||||
// // }
|
||||
// }
|
||||
|
||||
// private resetFieldFormGroup(formGroup: UntypedFormGroup) {
|
||||
// //console.log('resetFieldFormGroup: ' + formGroup);
|
||||
// //TODO: implement this
|
||||
// // const renderStyle = formGroup.getRawValue().viewStyle.renderStyle;
|
||||
// // if (renderStyle === DatasetProfileFieldViewStyle.Validation || renderStyle === DatasetProfileFieldViewStyle.DatasetIdentifier) {
|
||||
// // formGroup.get('value').setValue({ identifier: '', type: '' });
|
||||
// // } else {
|
||||
// // formGroup.get('value').setValue(formGroup.get('defaultValue').value ? this.parseValue(formGroup.get('defaultValue').value.value) : undefined);
|
||||
// // }
|
||||
|
||||
// }
|
||||
|
||||
// private resetCompositeFieldFormGroup(formGroup: UntypedFormGroup) {
|
||||
// //console.log('resetCompositeFieldFormGroup: ' + formGroup);
|
||||
// //TODO: implement this
|
||||
// // (formGroup.get('fields') as UntypedFormArray).controls.forEach((element: UntypedFormGroup) => {
|
||||
// // this.resetFieldFormGroup(element);
|
||||
// // });
|
||||
// // (formGroup.get('multiplicityItems') as UntypedFormArray).controls.splice(0);
|
||||
// }
|
||||
// private _emitChangesIfNeeded(id: string, valueToBeSet: boolean) {
|
||||
// if (this.isVisibleMap[id]) {
|
||||
// if (this.isVisibleMap[id] != valueToBeSet) {
|
||||
// this._changeMade$.next();
|
||||
// }
|
||||
// } else {
|
||||
// this._changeMade$.next();
|
||||
// }
|
||||
// }
|
||||
// public get visibilityChange() {
|
||||
// return this._changeMade$.asObservable();
|
||||
// }
|
||||
// public getVisibilityDependency(targetId: string): VisibilityRuleSource[] | null {
|
||||
// //console.log('getVisibilityDependency: ' + targetId);
|
||||
// return this.visibilityRuleContext.rules.reduce((hasDependency, rule) => {
|
||||
// if (hasDependency) return hasDependency;
|
||||
|
||||
// if (rule.targetControlId === targetId) {
|
||||
// return rule.sourceVisibilityRules;
|
||||
// }
|
||||
|
||||
// return null;
|
||||
// }, null) as VisibilityRuleSource[];
|
||||
// }
|
||||
|
||||
// public getVisibilityTargets(sourceId: string): string[] {
|
||||
// console.log('getVisibilityTargets: ' + sourceId);
|
||||
// return this.visibilityRuleContext.rules.filter(x => {
|
||||
// const result = x.sourceVisibilityRules.filter(y => y.sourceControlId === sourceId);
|
||||
// return result.length;
|
||||
// }).map(x => x.targetControlId);
|
||||
// }
|
||||
|
||||
// // public appendVisibilityRule(rule: VisibilityRule): void{
|
||||
|
||||
// // const existingTargetRule = this.visibilityRuleContext.rules.find( r => r.targetControlId === rule.targetControlId);
|
||||
|
||||
// // if(existingTargetRule){
|
||||
// // rule.sourceVisibilityRules.forEach(svr =>{
|
||||
// // existingTargetRule.sourceVisibilityRules.push(svr);
|
||||
// // });
|
||||
// // }else{
|
||||
// // this.visibilityRuleContext.rules.push(rule);
|
||||
// // }
|
||||
|
||||
|
||||
// // }
|
||||
|
||||
|
||||
// //removes rule that has the specific id either as a source either as a target
|
||||
// public removeAllIdReferences(id: string): void {
|
||||
// //console.log('removeAllIdReferences: ' + id);
|
||||
|
||||
// // * Remove from visibility rues and visibility rules context
|
||||
|
||||
// //remove as a target
|
||||
// const temp = this.visibilityRuleContext.rules.map((x, i) => (x.targetControlId === id) ? i : null);
|
||||
// const indexes = temp.filter(x => x !== null);
|
||||
// indexes.reverse().forEach(index => this.visibilityRuleContext.rules.splice(index, 1));
|
||||
// this.isVisibleMap[id] = undefined;
|
||||
|
||||
|
||||
|
||||
// //remove as a source
|
||||
// const tbd = this.visibilityRuleContext.rules.reduce((to_be_deleted, rule, ruleIdx) => {
|
||||
// const idxs = rule.sourceVisibilityRules.map((x, i) => (x.sourceControlId === id) ? i : null).filter(x => x !== null);
|
||||
// idxs.reverse().forEach(index => rule.sourceVisibilityRules.splice(index, 1));
|
||||
|
||||
// if (!rule.sourceVisibilityRules.length) {
|
||||
// to_be_deleted.push(ruleIdx);
|
||||
// }
|
||||
// return to_be_deleted
|
||||
// }, []);
|
||||
|
||||
|
||||
// //clean up empty
|
||||
// tbd.reverse().forEach(index => {
|
||||
// this.visibilityRuleContext.rules.splice(index, 1);
|
||||
// });
|
||||
|
||||
|
||||
|
||||
// // * Remove from computational map
|
||||
|
||||
// // as a target
|
||||
// if (this.elementComputationalMap.get(id)) {
|
||||
// this.elementComputationalMap.delete(id);
|
||||
// }
|
||||
|
||||
|
||||
// // as a source
|
||||
// const keyIterator = this.elementComputationalMap.keys();
|
||||
// let currentKey = keyIterator.next();
|
||||
|
||||
|
||||
// while (!currentKey.done) {
|
||||
// const currentVals = this.elementComputationalMap.get(currentKey.value);
|
||||
// currentVals.delete(id);
|
||||
// currentKey = keyIterator.next();
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// public addNewRule(rule: Rule, currentVisibility = this.DEFAULTVISIBILITY): void {
|
||||
// //console.log('addNewRule: ' + rule + ' currentVisibility: ' + currentVisibility);
|
||||
|
||||
// const targetId = rule.targetField;
|
||||
// const sourceId = rule.sourceField;
|
||||
// this.visibilityRuleContext.addToVisibilityRulesContext(rule);
|
||||
|
||||
|
||||
// let visibilityMap = this.elementComputationalMap.get(targetId);
|
||||
|
||||
// if (!visibilityMap) {
|
||||
// visibilityMap = new Map<String, boolean>();
|
||||
// this.elementComputationalMap.set(targetId, visibilityMap);
|
||||
// }
|
||||
|
||||
// visibilityMap.set(sourceId, currentVisibility);
|
||||
// const isVisible = this._computeVisibility(targetId);
|
||||
|
||||
// this._emitChangesIfNeeded(targetId, isVisible);
|
||||
// this.isVisibleMap[targetId] = isVisible;
|
||||
// this.elementVisibilityMapSubject.next(this.isVisibleMap);
|
||||
// }
|
||||
|
||||
|
||||
// /**
|
||||
// * Check what sourceId hides or shows the target field
|
||||
// * return true if no rule found
|
||||
// */
|
||||
// public checkTargetVisibilityProvidedBySource(sourceId: string, targetId: string): boolean {
|
||||
// //console.log('checkTargetVisibilityProvidedBySource: ' + sourceId + ' targetId: ' + targetId);
|
||||
|
||||
// const computationalMap = this.elementComputationalMap.get(targetId);
|
||||
// if (computationalMap) {
|
||||
// return !!computationalMap.get(sourceId);
|
||||
// }
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// public getVisibilityRulesFromDescriptionTempalte(descriptionTemplate: DescriptionTemplate): Rule[] {
|
||||
// //console.log('getVisibilityRulesFromDescriptionTempalte: ' + descriptionTemplate);
|
||||
// const result: Rule[] = this.getVisibilityRulesFromDescriptionTempalteSections(descriptionTemplate?.definition?.pages);
|
||||
// return result;
|
||||
// }
|
||||
|
||||
// public getVisibilityRulesFromDescriptionTempalteSections(pages: DescriptionTemplatePage[]): Rule[] {
|
||||
// //console.log('getVisibilityRulesFromDescriptionTempalteSections: ' + sections);
|
||||
// const result: Rule[] = [];
|
||||
// pages.forEach(page => {
|
||||
// page?.sections?.forEach(section => {
|
||||
// if (section.sections != null) { result.push(...this.getVisibilityRulesFromDescriptionTempalteSections(section.sections)); };
|
||||
// section?.fieldSets?.forEach(fieldSet => {
|
||||
// fieldSet?.fields?.forEach(field => {
|
||||
// field.visibilityRules?.forEach(visibilityRule => {
|
||||
// result.push({
|
||||
// sourceField: field.id.toString(),
|
||||
// targetField: visibilityRule.target,
|
||||
// dateValue: visibilityRule.dateValue,
|
||||
// textValue: visibilityRule.textValue,
|
||||
// textListValue: visibilityRule.textListValue
|
||||
// })
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
|
||||
// class MapWithDefault extends Map<string, boolean> {
|
||||
// get(key) {
|
||||
// //console.log('MapWithDefault');
|
||||
// if (!this.has(key)) {
|
||||
// this.set(key, true);
|
||||
// }
|
||||
// return super.get(key);
|
||||
// }
|
||||
// }
|
|
@ -263,7 +263,7 @@ export class VisibilityRulesService {
|
|||
const fieldType: DescriptionTemplateFieldType = rule.field != null && rule.field.data != null ? rule.field.data.fieldType : DescriptionTemplateFieldType.FREE_TEXT;
|
||||
if ([DescriptionTemplateFieldType.FREE_TEXT, DescriptionTemplateFieldType.CHECK_BOX, DescriptionTemplateFieldType.TEXT_AREA,
|
||||
DescriptionTemplateFieldType.RICH_TEXT_AREA, DescriptionTemplateFieldType.UPLOAD, DescriptionTemplateFieldType.BOOLEAN_DECISION,
|
||||
DescriptionTemplateFieldType.RADIO_BOX, DescriptionTemplateFieldType.CURRENCY, DescriptionTemplateFieldType.SELECT].includes(fieldType) && field.textValue != null && field.textValue.length > 0) {
|
||||
DescriptionTemplateFieldType.RADIO_BOX, DescriptionTemplateFieldType.CURRENCY].includes(fieldType) && field.textValue != null && field.textValue.length > 0) {
|
||||
if (DescriptionTemplateFieldType.UPLOAD == fieldType){
|
||||
return false; //not apply visibility logic
|
||||
} else {
|
||||
|
|
|
@ -71,10 +71,10 @@ public class InAppNotificationController {
|
|||
@PostMapping("query")
|
||||
public QueryResult<InAppNotification> Query(@RequestBody InAppNotificationLookup lookup) throws MyApplicationException, MyForbiddenException, InvalidApplicationException {
|
||||
logger.debug("querying {}", InAppNotification.class.getSimpleName());
|
||||
|
||||
this.censorFactory.censor(InAppNotificationCensor.class).censor(lookup.getProject());
|
||||
|
||||
UUID userId = this.userScope.getUserId();
|
||||
|
||||
this.censorFactory.censor(InAppNotificationCensor.class).censor(lookup.getProject(), userId);
|
||||
|
||||
if (userId == null) throw new MyForbiddenException(this.errors.getNonPersonPrincipal().getCode(), this.errors.getNonPersonPrincipal().getMessage());
|
||||
InAppNotificationQuery query = lookup.enrich(this.queryFactory).userId(userId);
|
||||
List<InAppNotificationEntity> data = query.collectAs(lookup.getProject());
|
||||
|
@ -88,12 +88,13 @@ public class InAppNotificationController {
|
|||
|
||||
@GetMapping("{id}")
|
||||
@Transactional
|
||||
public InAppNotification Get(@PathVariable UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
||||
public InAppNotification Get(@PathVariable UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException {
|
||||
logger.debug(new MapLogEntry("retrieving" + InAppNotification.class.getSimpleName()).And("id", id).And("fields", fieldSet));
|
||||
|
||||
this.censorFactory.censor(InAppNotificationCensor.class).censor(fieldSet);
|
||||
UUID userId = this.userScope.getUserId();
|
||||
this.censorFactory.censor(InAppNotificationCensor.class).censor(fieldSet, userId);
|
||||
|
||||
InAppNotificationQuery query = this.queryFactory.query(InAppNotificationQuery.class).authorize(AuthorizationFlags.OwnerOrPermission).ids(id);
|
||||
InAppNotificationQuery query = this.queryFactory.query(InAppNotificationQuery.class).authorize(AuthorizationFlags.OwnerOrPermission).userId(userId).ids(id);
|
||||
InAppNotification model = this.builderFactory.builder(InAppNotificationBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.firstAs(fieldSet));
|
||||
if (model == null)
|
||||
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Notification.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
@ -142,7 +143,7 @@ public class InAppNotificationController {
|
|||
UUID userId = this.userScope.getUserId();
|
||||
if (userId == null) throw new MyForbiddenException(this.errors.getNonPersonPrincipal().getCode(), this.errors.getNonPersonPrincipal().getMessage());
|
||||
|
||||
this.censorFactory.censor(InAppNotificationCensor.class).censor(new BaseFieldSet(InAppNotification.Field.ID));
|
||||
this.censorFactory.censor(InAppNotificationCensor.class).censor(new BaseFieldSet(InAppNotification.Field.ID), userId);
|
||||
|
||||
InAppNotificationQuery query = this.queryFactory.query(InAppNotificationQuery.class).isActive(IsActive.Active).trackingState(NotificationInAppTracking.STORED).userId(userId);
|
||||
int count = Math.toIntExact(query.count());
|
||||
|
|
|
@ -66,7 +66,7 @@ public class UserNotificationPreferenceController {
|
|||
public QueryResult<UserNotificationPreference> query(@RequestBody UserNotificationPreferenceLookup lookup) throws MyApplicationException, MyForbiddenException {
|
||||
logger.debug("querying {}", UserNotificationPreference.class.getSimpleName());
|
||||
|
||||
this.censorFactory.censor(UserNotificationPreferenceCensor.class).censor(lookup.getProject());
|
||||
this.censorFactory.censor(UserNotificationPreferenceCensor.class).censor(lookup.getProject(), null);
|
||||
|
||||
UserNotificationPreferenceQuery query = lookup.enrich(this.queryFactory);
|
||||
List<UserNotificationPreferenceEntity> data = query.collectAs(lookup.getProject());
|
||||
|
@ -83,7 +83,7 @@ public class UserNotificationPreferenceController {
|
|||
public UserNotificationPreference current(@PathVariable UUID userId, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
||||
logger.debug(new MapLogEntry("retrieving" + UserNotificationPreference.class.getSimpleName()).And("userId", userId).And("fields", fieldSet));
|
||||
|
||||
this.censorFactory.censor(UserNotificationPreferenceCensor.class).censor(fieldSet);
|
||||
this.censorFactory.censor(UserNotificationPreferenceCensor.class).censor(fieldSet, userId);
|
||||
|
||||
UserNotificationPreferenceQuery query = this.queryFactory.query(UserNotificationPreferenceQuery.class).userId(userId);
|
||||
UserNotificationPreference model = this.builderFactory.builder(UserNotificationPreferenceBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.firstAs(fieldSet));
|
||||
|
|
|
@ -39,9 +39,6 @@ cache:
|
|||
enableRecordStats: false
|
||||
expireAfterWriteSeconds: 60
|
||||
mapCaches:
|
||||
- names: [ cacheB ]
|
||||
allowNullValues: true
|
||||
storeByValue: true
|
||||
apiKey:
|
||||
name: apikey
|
||||
keyPattern: resolve_$keyhash$:v0
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
spring:
|
||||
jpa:
|
||||
properties:
|
||||
org:
|
||||
hibernate:
|
||||
flushMode: MANUAL
|
||||
hibernate:
|
||||
globally_quoted_identifiers: true
|
||||
ddl-auto: validate
|
||||
dialect: org.hibernate.dialect.PostgreSQLDialect
|
||||
hibernate:
|
||||
|
@ -16,9 +20,10 @@ spring:
|
|||
hikari:
|
||||
connection-timeout: 30000
|
||||
minimum-idle: 3
|
||||
maximum-pool-size: 5
|
||||
maximum-pool-size: 10
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 1800000
|
||||
|
||||
|
||||
naming-strategy:
|
||||
prefix: ntf_
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
spring:
|
||||
mail:
|
||||
host: ${MAIL_HOST:}
|
||||
port: ${MAIL_PORT:}
|
||||
username: ${MAIL_USERNAME:}
|
||||
password: ${MAIL_PASSWORD:}
|
||||
host: ${MAIL_HOST}
|
||||
port: ${MAIL_PORT}
|
||||
username: ${MAIL_USERNAME}
|
||||
password: ${MAIL_PASSWORD}
|
||||
properties:
|
||||
mail:
|
||||
smtp:
|
||||
auth: ${MAIL_AUTH:}
|
||||
auth: ${MAIL_AUTH}
|
||||
starttls:
|
||||
enable: ${MAIL_TLS:}
|
||||
enable: ${MAIL_TLS}
|
||||
email:
|
||||
address: ${MAIL_ADDRESS:}
|
||||
address: ${MAIL_ADDRESS}
|
|
@ -37,3 +37,5 @@ idpclient:
|
|||
- type: azp
|
||||
Authorities:
|
||||
- type: authorities
|
||||
ExternalProviderName:
|
||||
- type: identity_provider
|
|
@ -5,26 +5,26 @@ permissions:
|
|||
# Tenants
|
||||
BrowseTenant:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
EditTenant:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
DeleteTenant:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
claims: [ ]
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
AllowNoTenant:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
claims: [ ]
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
|
@ -32,21 +32,19 @@ permissions:
|
|||
# Users
|
||||
BrowseUser:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- tenantadmin
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: true
|
||||
allowAuthenticated: false
|
||||
EditUser:
|
||||
roles:
|
||||
- admin
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
DeleteUser:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
claims: [ ]
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
|
@ -54,20 +52,19 @@ permissions:
|
|||
# UserContactInfo
|
||||
BrowseUserContactInfo:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: true
|
||||
allowAuthenticated: false
|
||||
EditUserContactInfo:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- user
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
DeleteUserContactInfo:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
claims: [ ]
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
|
@ -94,27 +91,26 @@ permissions:
|
|||
#Tenant Configuration
|
||||
BrowseTenantConfiguration:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
EditTenantConfiguration:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
#User Notification Preference
|
||||
BrowseUserNotificationPreference:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: true
|
||||
allowAuthenticated: false
|
||||
EditUserNotificationPreference:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- user
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
|
@ -122,26 +118,25 @@ permissions:
|
|||
# ViewPage Permissions
|
||||
ViewNotificationPage:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
ViewNotificationEventRulePage:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
ViewInAppNotificationPage:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- tenantadmin
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
ViewNotificationTemplatePage:
|
||||
roles:
|
||||
- ic-sti-superuser
|
||||
- Admin
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
|
@ -170,7 +165,6 @@ permissions:
|
|||
BrowseInAppNotification:
|
||||
roles:
|
||||
- Admin
|
||||
- User
|
||||
clients: [ ]
|
||||
allowAnonymous: false
|
||||
allowAuthenticated: false
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
web:
|
||||
security:
|
||||
idp:
|
||||
resource:
|
||||
jwt:
|
||||
audiences: [ "dmp_notification" ]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue