Compare commits
94 Commits
Author | SHA1 | Date |
---|---|---|
Diamantis Tziotzios | e8aef281d4 | |
Diamantis Tziotzios | 00c6978594 | |
Diamantis Tziotzios | 3adb518e61 | |
Konstantina Galouni | eb74ef86b9 | |
Diamantis Tziotzios | a1ee9c82bc | |
Diamantis Tziotzios | 5e5bd39313 | |
Diamantis Tziotzios | 5e99cef60e | |
Diamantis Tziotzios | cc7edc2f49 | |
Diamantis Tziotzios | a1849c64ca | |
Diamantis Tziotzios | 192220161b | |
George Kalampokis | 87758c3e9a | |
Diamantis Tziotzios | 83342f5afa | |
Diamantis Tziotzios | 65cdb3b6ea | |
Diamantis Tziotzios | 536ba9b900 | |
Alexandros Mandilaras | 6bd3302788 | |
Diamantis Tziotzios | 4970f5812f | |
Diamantis Tziotzios | 9fed92dbcb | |
Diamantis Tziotzios | 44dab9c19a | |
Alexandros Mandilaras | 54f911d826 | |
Diamantis Tziotzios | 9879050eab | |
Diamantis Tziotzios | 8a41a7dcd9 | |
Diamantis Tziotzios | d60cc144d5 | |
Georgios Kakaletris | 9c37e5a073 | |
Georgios Kakaletris | 444c1aacb1 | |
Diamantis Tziotzios | 59d7383947 | |
Diamantis Tziotzios | 6caa1af134 | |
George Kalampokis | 74a6019a72 | |
George Kalampokis | 5c903c0f48 | |
George Kalampokis | ec8f6a6d48 | |
Bernaldo Mihasi | ecd86f413a | |
Bernaldo Mihasi | c238615b50 | |
Bernaldo Mihasi | 10d0f1fb0e | |
Bernaldo Mihasi | 846405435c | |
Bernaldo Mihasi | dfc9e14003 | |
Bernaldo Mihasi | bc1894586b | |
Bernaldo Mihasi | 2bf0a857bc | |
Bernaldo Mihasi | 3d10e8ad28 | |
Bernaldo Mihasi | 53b61853e1 | |
Bernaldo Mihasi | d644b1dc91 | |
Diamantis Tziotzios | 50c96ef821 | |
Konstantina Galouni | 0adc7044ab | |
Konstantina Galouni | 13e62fd409 | |
Diamantis Tziotzios | 7185b5d117 | |
George Kalampokis | 5f131b9823 | |
Diamantis Tziotzios | 93320f7c94 | |
Diamantis Tziotzios | 876d99ce38 | |
George Kalampokis | 7a71110033 | |
Diamantis Tziotzios | 14c267c97e | |
Diamantis Tziotzios | b04b35d62b | |
Diamantis Tziotzios | 7a8375b988 | |
Diamantis Tziotzios | 895dbcf098 | |
Diamantis Tziotzios | bd15b1e2c7 | |
George Kalampokis | faabd343a9 | |
George Kalampokis | e5a929f259 | |
George Kalampokis | d1fc10854c | |
George Kalampokis | 2537923dc0 | |
George Kalampokis | c1adbe283a | |
George Kalampokis | 1c365a191e | |
Kristian Ntavidi | 82c5586067 | |
George Kalampokis | 04f230dff1 | |
George Kalampokis | 72d88d9db4 | |
George Kalampokis | 143a4c0214 | |
George Kalampokis | e7e5ed02b3 | |
George Kalampokis | b5fcc5971e | |
Diamantis Tziotzios | c16c35225f | |
Diamantis Tziotzios | f5d266554b | |
Diamantis Tziotzios | db31597fc0 | |
Diamantis Tziotzios | 9f5054668e | |
George Kalampokis | 38986ef67b | |
Diamantis Tziotzios | bff260b85b | |
George Kalampokis | 9519300dc4 | |
George Kalampokis | 9373d3e038 | |
dtziotzios | d971f02a94 | |
Georgios Kakaletris | d3915e26e7 | |
George Kalampokis | c028aad615 | |
Diamantis Tziotzios | 4ee39074a3 | |
Diamantis Tziotzios | 1b4952a909 | |
Diamantis Tziotzios | 3ada5a0d3d | |
Diamantis Tziotzios | 63ee865dd9 | |
Diamantis Tziotzios | 2a52138124 | |
Diamantis Tziotzios | 7cf64c18f2 | |
Diamantis Tziotzios | 71d317bab7 | |
Ioannis Kalyvas | cd8b3448f5 | |
Ioannis Kalyvas | c3d4cb6fdd | |
Ioannis Kalyvas | b0ccac191f | |
Ioannis Kalyvas | 3b1f37ef22 | |
Ioannis Kalyvas | b8e040ee94 | |
Ioannis Kalyvas | 50444a0b73 | |
Diamantis Tziotzios | 85bdb7fad1 | |
annabakouli | b2e49fbb8a | |
Diamantis Tziotzios | bfc6b63067 | |
Nikolaos Laskaris | 9941c96dc2 | |
Nikolaos Laskaris | 06272c79da | |
Nikolaos Laskaris | a00eec68d8 |
|
@ -46,11 +46,6 @@ ELK.Docker/shared/data-elk/
|
||||||
.settings/
|
.settings/
|
||||||
bin/
|
bin/
|
||||||
*.classpath
|
*.classpath
|
||||||
.run
|
|
||||||
openDMP/dmp-backend/uploads/
|
openDMP/dmp-backend/uploads/
|
||||||
openDMP/dmp-backend/tmp/
|
openDMP/dmp-backend/tmp/
|
||||||
logs/
|
dmp-frontend/.angular/
|
||||||
dmp-backend/web/src/main/resources/certificates/
|
|
||||||
/storage/
|
|
||||||
dmp-backend/target/classes/
|
|
||||||
dmp-backend/core/target/maven-archiver/
|
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
|
||||||
|
**Important note: The deployment, troubleshooting, maintenance and operation of on-premises / self-served OpenDMP instances for development, testing or production use, shall be the sole responsibility of the adopter. No support is guaranteed by OpenDMP implentation team for issues that may be encountered during deployment, extension or operation of such installations.**
|
||||||
|
|
||||||
|
**Documentation is provided on a best-effort basis for the code and processes around the development, deployment and operation of OpenDMP. If you find any misalignment of the actual processes with the related documentation, please let us know so that the misalignment is addressed for the benefit of future adopters.**
|
||||||
|
|
||||||
|
|
||||||
# Using Docker Compose with Argos
|
# Using Docker Compose with Argos
|
||||||
|
|
||||||
ARGOS is an open extensible service that simplifies the management, validation, monitoring and maintenance and of Data Management Plans. It allows actors (researchers, managers, supervisors etc) to create actionable DMPs that may be freely exchanged among infrastructures for carrying out specific aspects of the Data management process in accordance with the intentions and commitment of Data owners.
|
ARGOS is an open extensible service that simplifies the management, validation, monitoring and maintenance and of Data Management Plans. It allows actors (researchers, managers, supervisors etc) to create actionable DMPs that may be freely exchanged among infrastructures for carrying out specific aspects of the Data management process in accordance with the intentions and commitment of Data owners.
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
####################################### Build stage #######################################
|
|
||||||
FROM maven:3.9-eclipse-temurin-21-alpine AS build-stage
|
|
||||||
|
|
||||||
ARG MAVEN_ACCOUNT_USR
|
|
||||||
ARG MAVEN_ACCOUNT_PSW
|
|
||||||
ARG REVISION
|
|
||||||
ARG PROFILE
|
|
||||||
ARG DEV_PROFILE_URL
|
|
||||||
ENV server_username=$MAVEN_ACCOUNT_USR
|
|
||||||
ENV server_password=$MAVEN_ACCOUNT_PSW
|
|
||||||
|
|
||||||
COPY pom.xml /build/
|
|
||||||
COPY annotation /build/annotation/
|
|
||||||
COPY annotation-web /build/annotation-web/
|
|
||||||
COPY settings.xml /root/.m2/settings.xml
|
|
||||||
RUN rm -f /build/annotation-web/src/main/resources/config/app.env
|
|
||||||
RUN rm -f /build/annotation-web/src/main/resources/config/*-devel.yml
|
|
||||||
RUN rm -f /build/annotation-web/src/main/resources/logging/*.xml
|
|
||||||
RUN rm -f /build/annotation-web/src/main/resources/certificates/*.crt
|
|
||||||
|
|
||||||
WORKDIR /build/
|
|
||||||
|
|
||||||
RUN mvn -Drevision=${REVISION} -DdevProfileUrl=${DEV_PROFILE_URL} -P${PROFILE} dependency:go-offline
|
|
||||||
# Build project
|
|
||||||
RUN mvn -Drevision=${REVISION} -DdevProfileUrl=${DEV_PROFILE_URL} -P${PROFILE} clean package
|
|
||||||
|
|
||||||
######################################## Run Stage ########################################
|
|
||||||
FROM eclipse-temurin:21-jre-ubi9-minimal
|
|
||||||
|
|
||||||
ARG PROFILE
|
|
||||||
ARG REVISION
|
|
||||||
ENV SERVER_PORT=8080
|
|
||||||
EXPOSE ${SERVER_PORT}
|
|
||||||
|
|
||||||
COPY --from=build-stage /build/annotation-web/target/annotation-web-${REVISION}.jar /app/annotation-web.jar
|
|
||||||
|
|
||||||
ENTRYPOINT ["java","-Dspring.config.additional-location=file:/config/","-Dspring.profiles.active=${PROFILE}","-Djava.security.egd=file:/dev/./urandom","-jar","/app/annotation-web.jar"]
|
|
|
@ -1,33 +0,0 @@
|
||||||
HELP.md
|
|
||||||
target/
|
|
||||||
!.mvn/wrapper/maven-wrapper.jar
|
|
||||||
!**/src/main/**/target/
|
|
||||||
!**/src/test/**/target/
|
|
||||||
|
|
||||||
### STS ###
|
|
||||||
.apt_generated
|
|
||||||
.classpath
|
|
||||||
.factorypath
|
|
||||||
.project
|
|
||||||
.settings
|
|
||||||
.springBeans
|
|
||||||
.sts4-cache
|
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
|
||||||
.idea
|
|
||||||
*.iws
|
|
||||||
*.iml
|
|
||||||
*.ipr
|
|
||||||
|
|
||||||
### NetBeans ###
|
|
||||||
/nbproject/private/
|
|
||||||
/nbbuild/
|
|
||||||
/dist/
|
|
||||||
/nbdist/
|
|
||||||
/.nb-gradle/
|
|
||||||
build/
|
|
||||||
!**/src/main/**/build/
|
|
||||||
!**/src/test/**/build/
|
|
||||||
|
|
||||||
### VS Code ###
|
|
||||||
.vscode/
|
|
|
@ -1,91 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>annotation-service-parent</artifactId>
|
|
||||||
<version>${revision}</version>
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>annotation-web</artifactId>
|
|
||||||
<version>${revision}</version>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<maven.compiler.release>21</maven.compiler.release>
|
|
||||||
<maven.compiler.source>21</maven.compiler.source>
|
|
||||||
<maven.compiler.target>21</maven.compiler.target>
|
|
||||||
<revision>1.0.0-SNAPSHOT</revision>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-validation</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.postgresql</groupId>
|
|
||||||
<artifactId>postgresql</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hibernate.orm</groupId>
|
|
||||||
<artifactId>hibernate-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>annotation</artifactId>
|
|
||||||
<version>${revision}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>oidc-authz</artifactId>
|
|
||||||
<version>2.1.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>cache</artifactId>
|
|
||||||
<version>2.2.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>exceptions-web</artifactId>
|
|
||||||
<version>2.1.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>cors-web</artifactId>
|
|
||||||
<version>2.1.0</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,26 +0,0 @@
|
||||||
package gr.cite.annotation.web;
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
|
||||||
|
|
||||||
@SpringBootApplication(
|
|
||||||
scanBasePackages = {
|
|
||||||
"eu.eudat",
|
|
||||||
"gr.cite",
|
|
||||||
"gr.cite.queueoutbox",
|
|
||||||
"gr.cite.queueinbox",
|
|
||||||
"gr.cite.annotation.integrationevent",
|
|
||||||
"gr.cite.tools",
|
|
||||||
"gr.cite.commons"})
|
|
||||||
@EntityScan({
|
|
||||||
"gr.cite.annotation.data"})
|
|
||||||
@EnableAsync
|
|
||||||
public class AnnotationApplication {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(AnnotationApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package gr.cite.annotation.web;
|
|
||||||
|
|
||||||
import gr.cite.annotation.web.scope.tenant.TenantInterceptor;
|
|
||||||
import gr.cite.annotation.web.scope.tenant.TenantScopeClaimInterceptor;
|
|
||||||
import gr.cite.annotation.web.scope.tenant.TenantScopeHeaderInterceptor;
|
|
||||||
import gr.cite.annotation.web.scope.user.UserInterceptor;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class WebConfiguration implements WebMvcConfigurer {
|
|
||||||
private final TenantInterceptor tenantInterceptor;
|
|
||||||
private final TenantScopeHeaderInterceptor scopeHeaderInterceptor;
|
|
||||||
private final TenantScopeClaimInterceptor scopeClaimInterceptor;
|
|
||||||
private final UserInterceptor userInterceptor;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public WebConfiguration(
|
|
||||||
TenantInterceptor tenantInterceptor,
|
|
||||||
TenantScopeHeaderInterceptor scopeHeaderInterceptor,
|
|
||||||
TenantScopeClaimInterceptor scopeClaimInterceptor,
|
|
||||||
UserInterceptor userInterceptor
|
|
||||||
) {
|
|
||||||
this.tenantInterceptor = tenantInterceptor;
|
|
||||||
this.scopeHeaderInterceptor = scopeHeaderInterceptor;
|
|
||||||
this.scopeClaimInterceptor = scopeClaimInterceptor;
|
|
||||||
this.userInterceptor = userInterceptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
|
||||||
int order = 1;
|
|
||||||
registry.addWebRequestInterceptor(scopeHeaderInterceptor).order(order++);
|
|
||||||
registry.addWebRequestInterceptor(scopeClaimInterceptor).order(order++);
|
|
||||||
registry.addWebRequestInterceptor(userInterceptor).order(order++);
|
|
||||||
registry.addWebRequestInterceptor(tenantInterceptor).order(order++);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
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,44 +0,0 @@
|
||||||
package gr.cite.annotation.web.authorization;
|
|
||||||
|
|
||||||
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 gr.cite.annotation.authorization.OwnedAuthorizationRequirement;
|
|
||||||
import gr.cite.annotation.authorization.OwnedResource;
|
|
||||||
import gr.cite.annotation.common.scope.user.UserScope;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
@Component("ownedAuthorizationHandler")
|
|
||||||
public class OwnedAuthorizationHandler extends AuthorizationHandler<OwnedAuthorizationRequirement> {
|
|
||||||
|
|
||||||
private final UserScope userScope;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public OwnedAuthorizationHandler(UserScope userScope) {
|
|
||||||
this.userScope = userScope;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int handleRequirement(AuthorizationHandlerContext context, Object resource, AuthorizationRequirement requirement) {
|
|
||||||
OwnedAuthorizationRequirement req = (OwnedAuthorizationRequirement) requirement;
|
|
||||||
|
|
||||||
OwnedResource rs = (OwnedResource) resource;
|
|
||||||
|
|
||||||
boolean isAuthenticated = ((MyPrincipal) context.getPrincipal()).isAuthenticated();
|
|
||||||
if (!isAuthenticated) return ACCESS_NOT_DETERMINED;
|
|
||||||
|
|
||||||
if (this.userScope.getUserIdSafe() == null) return ACCESS_NOT_DETERMINED;
|
|
||||||
|
|
||||||
if (rs != null && rs.getUserIds() != null && rs.getUserIds().contains(this.userScope.getUserIdSafe())) return ACCESS_GRANTED;
|
|
||||||
|
|
||||||
return ACCESS_NOT_DETERMINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends AuthorizationRequirement> supporting() {
|
|
||||||
return OwnedAuthorizationRequirement.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package gr.cite.annotation.web.config;
|
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
|
||||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class AppMessageSourceConfiguration {
|
|
||||||
@Bean
|
|
||||||
public MessageSource messageSource() {
|
|
||||||
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
|
|
||||||
messageSource.setBasename("classpath:messages/messages");
|
|
||||||
messageSource.setDefaultEncoding("UTF-8");
|
|
||||||
return messageSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public LocalValidatorFactoryBean getValidator() {
|
|
||||||
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
|
|
||||||
bean.setValidationMessageSource(messageSource());
|
|
||||||
return bean;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,152 +0,0 @@
|
||||||
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;
|
|
||||||
import gr.cite.commons.web.authz.policy.AuthorizationRequirementMapper;
|
|
||||||
import gr.cite.commons.web.authz.policy.AuthorizationResource;
|
|
||||||
import gr.cite.commons.web.authz.policy.resolver.AuthorizationPolicyConfigurer;
|
|
||||||
import gr.cite.commons.web.authz.policy.resolver.AuthorizationPolicyResolverStrategy;
|
|
||||||
import gr.cite.commons.web.oidc.configuration.WebSecurityProperties;
|
|
||||||
import gr.cite.annotation.authorization.OwnedAuthorizationRequirement;
|
|
||||||
import gr.cite.annotation.authorization.OwnedResource;
|
|
||||||
import gr.cite.annotation.web.authorization.OwnedAuthorizationHandler;
|
|
||||||
import jakarta.servlet.Filter;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.security.authentication.AuthenticationManagerResolver;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
|
||||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
|
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
|
||||||
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
public class SecurityConfiguration {
|
|
||||||
|
|
||||||
private final WebSecurityProperties webSecurityProperties;
|
|
||||||
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("affiliatedAuthorizationHandler") AffiliatedAuthorizationHandler affiliatedAuthorizationHandler) {
|
|
||||||
this.webSecurityProperties = webSecurityProperties;
|
|
||||||
this.authenticationManagerResolver = authenticationManagerResolver;
|
|
||||||
this.apiKeyFilter = apiKeyFilter;
|
|
||||||
this.ownedAuthorizationHandler = ownedAuthorizationHandler;
|
|
||||||
this.affiliatedAuthorizationHandler = affiliatedAuthorizationHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
|
||||||
HttpSecurity tempHttp = http
|
|
||||||
.csrf(AbstractHttpConfigurer::disable)
|
|
||||||
.cors(httpSecurityCorsConfigurer -> {})
|
|
||||||
.headers(httpSecurityHeadersConfigurer -> httpSecurityHeadersConfigurer.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
|
|
||||||
.addFilterBefore(apiKeyFilter, AbstractPreAuthenticatedProcessingFilter.class)
|
|
||||||
.authorizeHttpRequests(authRequest ->
|
|
||||||
authRequest.requestMatchers(buildAntPatterns(webSecurityProperties.getAllowedEndpoints())).anonymous()
|
|
||||||
.requestMatchers(buildAntPatterns(webSecurityProperties.getAuthorizedEndpoints())).authenticated())
|
|
||||||
.sessionManagement( sessionManagementConfigurer-> sessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.NEVER))
|
|
||||||
.oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(authenticationManagerResolver));
|
|
||||||
return tempHttp.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
AuthorizationPolicyConfigurer authorizationPolicyConfigurer() {
|
|
||||||
return new AuthorizationPolicyConfigurer() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthorizationPolicyResolverStrategy strategy() {
|
|
||||||
return AuthorizationPolicyResolverStrategy.STRICT_CONSENSUS_BASED;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Here you can register your custom authorization handlers, which will get used as well as the existing ones
|
|
||||||
//This is optional and can be omitted
|
|
||||||
//If not set / set to null, only the default authorization handlers will be used
|
|
||||||
@Override
|
|
||||||
public List<AuthorizationHandler<? extends AuthorizationRequirement>> addCustomHandlers() {
|
|
||||||
return List.of(affiliatedAuthorizationHandler, ownedAuthorizationHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Here you can register your custom authorization requirements (if any)
|
|
||||||
//This is optional and can be omitted
|
|
||||||
//If not set / set to null, only the default authorization requirements will be used
|
|
||||||
@Override
|
|
||||||
public List<? extends AuthorizationRequirement> extendRequirements() {
|
|
||||||
return List.of(
|
|
||||||
// new TimeOfDayAuthorizationRequirement(new TimeOfDay("08:00","16:00"), true)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Here you can select handlers you want to disable by providing the classes they are implemented by
|
|
||||||
//You can disable any handler (including any custom one)
|
|
||||||
//This is optional and can be omitted
|
|
||||||
//If not set / set to null, all the handlers will be invoked, based on their requirement support
|
|
||||||
//In the example below, the default client handler will be ignored by the resolver
|
|
||||||
@Override
|
|
||||||
public List<Class<? extends AuthorizationHandler<? extends AuthorizationRequirement>>> disableHandlers() {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
AuthorizationRequirementMapper authorizationRequirementMapper() {
|
|
||||||
return new AuthorizationRequirementMapper() {
|
|
||||||
@Override
|
|
||||||
public AuthorizationRequirement map(AuthorizationResource resource, boolean matchAll, String[] permissions) {
|
|
||||||
Class<?> type = resource.getClass();
|
|
||||||
if (!AuthorizationResource.class.isAssignableFrom(type)) throw new IllegalArgumentException("resource");
|
|
||||||
|
|
||||||
if (OwnedResource.class.equals(type)) {
|
|
||||||
return new OwnedAuthorizationRequirement();
|
|
||||||
}
|
|
||||||
if (AffiliatedResource.class.equals(type)) {
|
|
||||||
return new AffiliatedAuthorizationRequirement(matchAll, permissions);
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("resource");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] buildAntPatterns(Set<String> endpoints) {
|
|
||||||
if (endpoints == null) {
|
|
||||||
return new String[0];
|
|
||||||
}
|
|
||||||
return endpoints.stream()
|
|
||||||
.filter(endpoint -> endpoint != null && !endpoint.isBlank())
|
|
||||||
.map(endpoint -> "/" + stripUnnecessaryCharacters(endpoint) + "/**")
|
|
||||||
.toArray(String[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String stripUnnecessaryCharacters(String endpoint) {
|
|
||||||
endpoint = endpoint.strip();
|
|
||||||
if (endpoint.startsWith("/")) {
|
|
||||||
endpoint = endpoint.substring(1);
|
|
||||||
}
|
|
||||||
if (endpoint.endsWith("/")) {
|
|
||||||
endpoint = endpoint.substring(0, endpoint.length() - 1);
|
|
||||||
}
|
|
||||||
return endpoint;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,193 +0,0 @@
|
||||||
package gr.cite.annotation.web.controllerhandler;
|
|
||||||
|
|
||||||
import gr.cite.annotation.common.JsonHandlingService;
|
|
||||||
import gr.cite.tools.exception.*;
|
|
||||||
import gr.cite.tools.logging.LoggerService;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
|
||||||
import org.springframework.web.context.request.WebRequest;
|
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@RestControllerAdvice
|
|
||||||
@ControllerAdvice
|
|
||||||
public class GlobalExceptionHandler {
|
|
||||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(GlobalExceptionHandler.class));
|
|
||||||
|
|
||||||
private final JsonHandlingService jsonHandlingService;
|
|
||||||
|
|
||||||
public GlobalExceptionHandler(JsonHandlingService jsonHandlingService) {
|
|
||||||
this.jsonHandlingService = jsonHandlingService;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ExceptionHandler(Exception.class)
|
|
||||||
public ResponseEntity<?> handleUnexpectedErrors(Exception exception, WebRequest request) throws Exception {
|
|
||||||
HandledException handled = this.handleException(exception, request);
|
|
||||||
this.log(handled.getLevel(), exception, MessageFormat.format("returning code {0} and payload {1}", handled.getStatusCode(), handled.getMessage()));
|
|
||||||
return new ResponseEntity<>(handled.getMessage(), handled.getStatusCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void log(System.Logger.Level level, Exception e, String message) {
|
|
||||||
if (level != null) {
|
|
||||||
switch (level) {
|
|
||||||
case TRACE:
|
|
||||||
logger.trace(message, e);
|
|
||||||
break;
|
|
||||||
case DEBUG:
|
|
||||||
logger.debug(message, e);
|
|
||||||
break;
|
|
||||||
case INFO:
|
|
||||||
logger.info(message, e);
|
|
||||||
break;
|
|
||||||
case WARNING:
|
|
||||||
logger.warn(message, e);
|
|
||||||
break;
|
|
||||||
case ERROR:
|
|
||||||
logger.error(message, e);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public HandledException handleException(Exception exception, WebRequest request) throws Exception {
|
|
||||||
HttpStatus statusCode;
|
|
||||||
Map<String, Object> result;
|
|
||||||
System.Logger.Level logLevel;
|
|
||||||
|
|
||||||
switch (exception){
|
|
||||||
case MyNotFoundException myNotFoundException -> {
|
|
||||||
logLevel = System.Logger.Level.DEBUG;
|
|
||||||
statusCode = HttpStatus.NOT_FOUND;
|
|
||||||
int code = myNotFoundException.getCode();
|
|
||||||
if (code > 0) {
|
|
||||||
result = Map.ofEntries(
|
|
||||||
Map.entry("code", code),
|
|
||||||
Map.entry("error", myNotFoundException.getMessage())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = Map.ofEntries(
|
|
||||||
Map.entry("error", myNotFoundException.getMessage())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case MyUnauthorizedException myUnauthorizedException -> {
|
|
||||||
logLevel = System.Logger.Level.DEBUG;
|
|
||||||
statusCode = HttpStatus.UNAUTHORIZED;
|
|
||||||
int code = myUnauthorizedException.getCode();
|
|
||||||
if (code > 0) {
|
|
||||||
result = Map.ofEntries(
|
|
||||||
Map.entry("code", code),
|
|
||||||
Map.entry("error", myUnauthorizedException.getMessage())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = Map.ofEntries(
|
|
||||||
Map.entry("error", myUnauthorizedException.getMessage())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case MyForbiddenException myForbiddenException -> {
|
|
||||||
logLevel = System.Logger.Level.DEBUG;
|
|
||||||
statusCode = HttpStatus.FORBIDDEN;
|
|
||||||
int code = myForbiddenException.getCode();
|
|
||||||
if (code > 0) {
|
|
||||||
result = Map.ofEntries(
|
|
||||||
Map.entry("code", code),
|
|
||||||
Map.entry("error", myForbiddenException.getMessage())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = Map.ofEntries(
|
|
||||||
Map.entry("error", myForbiddenException.getMessage())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case MyValidationException myValidationException -> {
|
|
||||||
logLevel = System.Logger.Level.DEBUG;
|
|
||||||
statusCode = HttpStatus.BAD_REQUEST;
|
|
||||||
int code = myValidationException.getCode();
|
|
||||||
if (code > 0) {
|
|
||||||
result = Map.ofEntries(
|
|
||||||
Map.entry("code", code),
|
|
||||||
Map.entry("error", myValidationException.getMessage()),
|
|
||||||
Map.entry("message", myValidationException.getErrors())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = Map.ofEntries(
|
|
||||||
Map.entry("error", myValidationException.getMessage()),
|
|
||||||
Map.entry("message", myValidationException.getErrors())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case MyApplicationException myApplicationException -> {
|
|
||||||
logLevel = System.Logger.Level.ERROR;
|
|
||||||
statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
|
|
||||||
int code = myApplicationException.getCode();
|
|
||||||
if (code > 0) {
|
|
||||||
result = Map.ofEntries(
|
|
||||||
Map.entry("code", code),
|
|
||||||
Map.entry("error", myApplicationException.getMessage())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = Map.ofEntries(
|
|
||||||
Map.entry("error", myApplicationException.getMessage())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default -> {
|
|
||||||
logLevel = System.Logger.Level.ERROR;
|
|
||||||
statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
|
|
||||||
result = Map.ofEntries(
|
|
||||||
Map.entry("error", "System error")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
String serialization = this.jsonHandlingService.toJsonSafe(result);
|
|
||||||
return new HandledException(statusCode, serialization, logLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class HandledException{
|
|
||||||
public HttpStatus statusCode;
|
|
||||||
public String message;
|
|
||||||
public System.Logger.Level level;
|
|
||||||
|
|
||||||
public HandledException(HttpStatus statusCode, String message, System.Logger.Level level) {
|
|
||||||
this.statusCode = statusCode;
|
|
||||||
this.message = message;
|
|
||||||
this.level = level;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpStatus getStatusCode() {
|
|
||||||
return statusCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatusCode(HttpStatus statusCode) {
|
|
||||||
this.statusCode = statusCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMessage(String message) {
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public System.Logger.Level getLevel() {
|
|
||||||
return level;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLevel(System.Logger.Level level) {
|
|
||||||
this.level = level;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,132 +0,0 @@
|
||||||
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;
|
|
||||||
import gr.cite.annotation.model.censorship.AnnotationCensor;
|
|
||||||
import gr.cite.annotation.model.persist.AnnotationPersist;
|
|
||||||
import gr.cite.annotation.query.AnnotationQuery;
|
|
||||||
import gr.cite.annotation.query.lookup.AnnotationLookup;
|
|
||||||
import gr.cite.annotation.service.annotation.AnnotationService;
|
|
||||||
import gr.cite.annotation.web.model.QueryResult;
|
|
||||||
import gr.cite.tools.auditing.AuditService;
|
|
||||||
import gr.cite.tools.data.builder.BuilderFactory;
|
|
||||||
import gr.cite.tools.data.censor.CensorFactory;
|
|
||||||
import gr.cite.tools.data.query.QueryFactory;
|
|
||||||
import gr.cite.tools.exception.MyApplicationException;
|
|
||||||
import gr.cite.tools.exception.MyForbiddenException;
|
|
||||||
import gr.cite.tools.exception.MyNotFoundException;
|
|
||||||
import gr.cite.tools.fieldset.FieldSet;
|
|
||||||
import gr.cite.tools.logging.LoggerService;
|
|
||||||
import gr.cite.tools.logging.MapLogEntry;
|
|
||||||
import gr.cite.tools.validation.ValidationFilterAnnotation;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import jakarta.xml.bind.JAXBException;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.transform.TransformerException;
|
|
||||||
import java.util.AbstractMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping(path = "api/annotation", produces = MediaType.APPLICATION_JSON_VALUE)
|
|
||||||
public class AnnotationController {
|
|
||||||
|
|
||||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(AnnotationController.class));
|
|
||||||
|
|
||||||
private final CensorFactory censorFactory;
|
|
||||||
|
|
||||||
private final QueryFactory queryFactory;
|
|
||||||
|
|
||||||
private final BuilderFactory builderFactory;
|
|
||||||
|
|
||||||
private final AuditService auditService;
|
|
||||||
|
|
||||||
private final MessageSource messageSource;
|
|
||||||
|
|
||||||
private final AnnotationService annotationService;
|
|
||||||
|
|
||||||
public AnnotationController(CensorFactory censorFactory, QueryFactory queryFactory, BuilderFactory builderFactory, AuditService auditService, MessageSource messageSource, AnnotationService annotationService) {
|
|
||||||
this.censorFactory = censorFactory;
|
|
||||||
this.queryFactory = queryFactory;
|
|
||||||
this.builderFactory = builderFactory;
|
|
||||||
this.auditService = auditService;
|
|
||||||
this.messageSource = messageSource;
|
|
||||||
this.annotationService = annotationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("query")
|
|
||||||
public QueryResult<Annotation> query(@RequestBody AnnotationLookup lookup) {
|
|
||||||
logger.debug("querying {}", Annotation.class.getSimpleName());
|
|
||||||
|
|
||||||
this.censorFactory.censor(AnnotationCensor.class).censor(lookup.getProject(), null);
|
|
||||||
|
|
||||||
AnnotationQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrPermissionAssociated);
|
|
||||||
List<AnnotationEntity> data = query.collect();
|
|
||||||
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);
|
|
||||||
|
|
||||||
return new QueryResult<>(models, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("{id}")
|
|
||||||
public Annotation get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
|
||||||
logger.debug(new MapLogEntry("retrieving" + Annotation.class.getSimpleName()).And("id", id).And("fields", fieldSet));
|
|
||||||
|
|
||||||
this.censorFactory.censor(AnnotationCensor.class).censor(fieldSet, null);
|
|
||||||
|
|
||||||
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()));
|
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.Annotation_Lookup, Map.ofEntries(
|
|
||||||
new AbstractMap.SimpleEntry<String, Object>("id", id),
|
|
||||||
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
|
|
||||||
));
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("persist")
|
|
||||||
@Transactional
|
|
||||||
@ValidationFilterAnnotation(validator = AnnotationPersist.AnnotationPersistValidator.ValidatorName, argumentName = "model")
|
|
||||||
public Annotation persist(@RequestBody AnnotationPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException {
|
|
||||||
logger.debug(new MapLogEntry("persisting" + Annotation.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
|
|
||||||
|
|
||||||
this.censorFactory.censor(AnnotationCensor.class).censor(fieldSet, null);
|
|
||||||
|
|
||||||
Annotation persisted = this.annotationService.persist(model, fieldSet);
|
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.Annotation_Persist, Map.ofEntries(
|
|
||||||
new AbstractMap.SimpleEntry<String, Object>("model", model),
|
|
||||||
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
|
|
||||||
));
|
|
||||||
|
|
||||||
return persisted;
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("{id}")
|
|
||||||
@Transactional
|
|
||||||
public void delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException {
|
|
||||||
logger.debug(new MapLogEntry("retrieving" + Annotation.class.getSimpleName()).And("id", id));
|
|
||||||
|
|
||||||
this.annotationService.deleteAndSave(id);
|
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.Annotation_Delete, "id", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
package gr.cite.annotation.web.controllers;
|
|
||||||
|
|
||||||
import gr.cite.annotation.authorization.ClaimNames;
|
|
||||||
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
|
||||||
import gr.cite.commons.web.oidc.principal.MyPrincipal;
|
|
||||||
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
|
|
||||||
import gr.cite.annotation.audit.AuditableAction;
|
|
||||||
import gr.cite.annotation.common.scope.tenant.TenantScope;
|
|
||||||
import gr.cite.annotation.web.model.Account;
|
|
||||||
import gr.cite.annotation.web.model.AccountBuilder;
|
|
||||||
import gr.cite.tools.auditing.AuditService;
|
|
||||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
|
||||||
import gr.cite.tools.fieldset.FieldSet;
|
|
||||||
import gr.cite.tools.logging.LoggerService;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping(path = "api/annotation/principal", produces = MediaType.APPLICATION_JSON_VALUE)
|
|
||||||
public class PrincipalController {
|
|
||||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(PrincipalController.class));
|
|
||||||
private final AuditService auditService;
|
|
||||||
|
|
||||||
private final CurrentPrincipalResolver currentPrincipalResolver;
|
|
||||||
private final AccountBuilder accountBuilder;
|
|
||||||
private final ClaimExtractor claimExtractor;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public PrincipalController(
|
|
||||||
CurrentPrincipalResolver currentPrincipalResolver,
|
|
||||||
AccountBuilder accountBuilder,
|
|
||||||
AuditService auditService,
|
|
||||||
ClaimExtractor claimExtractor) {
|
|
||||||
this.currentPrincipalResolver = currentPrincipalResolver;
|
|
||||||
this.accountBuilder = accountBuilder;
|
|
||||||
this.auditService = auditService;
|
|
||||||
this.claimExtractor = claimExtractor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("me")
|
|
||||||
public Account me(FieldSet fieldSet) {
|
|
||||||
logger.debug("me");
|
|
||||||
|
|
||||||
|
|
||||||
if (fieldSet == null || fieldSet.isEmpty()) {
|
|
||||||
fieldSet = new BaseFieldSet(
|
|
||||||
Account._isAuthenticated,
|
|
||||||
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._subject),
|
|
||||||
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._userId),
|
|
||||||
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._name),
|
|
||||||
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._scope),
|
|
||||||
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._client),
|
|
||||||
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._issuedAt),
|
|
||||||
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._notBefore),
|
|
||||||
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._authenticatedAt),
|
|
||||||
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._expiresAt),
|
|
||||||
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._more),
|
|
||||||
Account._permissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal();
|
|
||||||
|
|
||||||
Account me = this.accountBuilder.build(fieldSet, principal);
|
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.Principal_Lookup);
|
|
||||||
//auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
|
|
||||||
|
|
||||||
return me;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("my-tenants")
|
|
||||||
public List<String> myTenants() {
|
|
||||||
logger.debug("my-tenants");
|
|
||||||
|
|
||||||
MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal();
|
|
||||||
List<String> tenants = this.claimExtractor.asStrings(principal, ClaimNames.TenantCodesClaimName);
|
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.Tenants_Lookup);
|
|
||||||
//auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
|
|
||||||
|
|
||||||
return tenants == null ? null : tenants.stream().distinct().collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,129 +0,0 @@
|
||||||
package gr.cite.annotation.web.controllers;
|
|
||||||
|
|
||||||
import gr.cite.annotation.audit.AuditableAction;
|
|
||||||
import gr.cite.annotation.authorization.AuthorizationFlags;
|
|
||||||
import gr.cite.annotation.common.enums.TenantConfigurationType;
|
|
||||||
import gr.cite.annotation.data.TenantConfigurationEntity;
|
|
||||||
import gr.cite.annotation.model.TenantConfiguration;
|
|
||||||
import gr.cite.annotation.model.builder.TenantConfigurationBuilder;
|
|
||||||
import gr.cite.annotation.model.censorship.TenantConfigurationCensor;
|
|
||||||
import gr.cite.annotation.model.persist.tenantconfiguration.TenantConfigurationEmailClientPersist;
|
|
||||||
import gr.cite.annotation.query.TenantConfigurationQuery;
|
|
||||||
import gr.cite.annotation.query.lookup.TenantConfigurationLookup;
|
|
||||||
import gr.cite.annotation.service.tenantconfiguration.TenantConfigurationService;
|
|
||||||
import gr.cite.annotation.web.model.QueryResult;
|
|
||||||
import gr.cite.tools.auditing.AuditService;
|
|
||||||
import gr.cite.tools.data.builder.BuilderFactory;
|
|
||||||
import gr.cite.tools.data.censor.CensorFactory;
|
|
||||||
import gr.cite.tools.data.query.QueryFactory;
|
|
||||||
import gr.cite.tools.exception.MyApplicationException;
|
|
||||||
import gr.cite.tools.exception.MyForbiddenException;
|
|
||||||
import gr.cite.tools.exception.MyNotFoundException;
|
|
||||||
import gr.cite.tools.fieldset.FieldSet;
|
|
||||||
import gr.cite.tools.logging.LoggerService;
|
|
||||||
import gr.cite.tools.logging.MapLogEntry;
|
|
||||||
import gr.cite.tools.validation.ValidationFilterAnnotation;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping(path = "api/annotation/tenant-configuration")
|
|
||||||
public class TenantConfigurationController {
|
|
||||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantConfigurationController.class));
|
|
||||||
|
|
||||||
private final BuilderFactory builderFactory;
|
|
||||||
private final AuditService auditService;
|
|
||||||
private final TenantConfigurationService tenantConfigurationService;
|
|
||||||
private final CensorFactory censorFactory;
|
|
||||||
private final QueryFactory queryFactory;
|
|
||||||
private final MessageSource messageSource;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public TenantConfigurationController(BuilderFactory builderFactory,
|
|
||||||
AuditService auditService,
|
|
||||||
TenantConfigurationService tenantConfigurationService, CensorFactory censorFactory,
|
|
||||||
QueryFactory queryFactory,
|
|
||||||
MessageSource messageSource) {
|
|
||||||
this.builderFactory = builderFactory;
|
|
||||||
this.auditService = auditService;
|
|
||||||
this.tenantConfigurationService = tenantConfigurationService;
|
|
||||||
this.censorFactory = censorFactory;
|
|
||||||
this.queryFactory = queryFactory;
|
|
||||||
this.messageSource = messageSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("query")
|
|
||||||
public QueryResult<TenantConfiguration> query(@RequestBody TenantConfigurationLookup lookup) throws MyApplicationException, MyForbiddenException {
|
|
||||||
logger.debug("querying {}", TenantConfiguration.class.getSimpleName());
|
|
||||||
|
|
||||||
this.censorFactory.censor(TenantConfigurationCensor.class).censor(lookup.getProject());
|
|
||||||
|
|
||||||
TenantConfigurationQuery query = lookup.enrich(this.queryFactory);
|
|
||||||
List<TenantConfigurationEntity> data = query.collectAs(lookup.getProject());
|
|
||||||
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);
|
|
||||||
|
|
||||||
return new QueryResult<>(models, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("{id}")
|
|
||||||
@Transactional
|
|
||||||
public TenantConfiguration get(@PathVariable UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
|
||||||
logger.debug(new MapLogEntry("retrieving" + TenantConfiguration.class.getSimpleName()).And("id", id).And("fields", fieldSet));
|
|
||||||
|
|
||||||
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.OwnerOrPermissionAssociated).build(fieldSet, query.firstAs(fieldSet));
|
|
||||||
if (model == null)
|
|
||||||
throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, TenantConfiguration.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.Tenant_Configuration_Lookup, Map.ofEntries(
|
|
||||||
new AbstractMap.SimpleEntry<String, Object>("id", id),
|
|
||||||
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
|
|
||||||
));
|
|
||||||
//this.auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("persist/email-client")
|
|
||||||
@Transactional
|
|
||||||
@ValidationFilterAnnotation(validator = TenantConfigurationEmailClientPersist.TenantConfigurationEmailClientPersistValidator.ValidatorName, argumentName = "model")
|
|
||||||
public TenantConfiguration persist(@RequestBody TenantConfigurationEmailClientPersist model, FieldSet fieldSet)
|
|
||||||
{
|
|
||||||
logger.debug(new MapLogEntry("persisting").And("type", TenantConfigurationType.EMAIL_CLIENT_CONFIGURATION).And("model", model).And("fields", fieldSet));
|
|
||||||
|
|
||||||
TenantConfiguration persisted = this.tenantConfigurationService.persist(model, fieldSet);
|
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.Tenant_Configuration_Persist, Map.of(
|
|
||||||
"type", TenantConfigurationType.EMAIL_CLIENT_CONFIGURATION,
|
|
||||||
"model", model,
|
|
||||||
"fields", fieldSet
|
|
||||||
));
|
|
||||||
//this._auditService.TrackIdentity(AuditableAction.IdentityTracking_Action);
|
|
||||||
|
|
||||||
return persisted;
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("{id}")
|
|
||||||
@Transactional
|
|
||||||
public void delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException {
|
|
||||||
logger.debug(new MapLogEntry("deleting" + TenantConfiguration.class.getSimpleName()).And("id", id));
|
|
||||||
|
|
||||||
this.tenantConfigurationService.deleteAndSave(id);
|
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.Tenant_Configuration_Delete, "id", id);
|
|
||||||
|
|
||||||
//this.auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,160 +0,0 @@
|
||||||
package gr.cite.annotation.web.model;
|
|
||||||
|
|
||||||
import gr.cite.tools.logging.annotation.LogSensitive;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class Account {
|
|
||||||
|
|
||||||
public static class PrincipalInfo {
|
|
||||||
|
|
||||||
public static final String _userId = "userId";
|
|
||||||
public UUID userId;
|
|
||||||
|
|
||||||
public UUID getUserId() {
|
|
||||||
return userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserId(UUID userId) {
|
|
||||||
this.userId = userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String _subject = "subject";
|
|
||||||
public UUID subject;
|
|
||||||
|
|
||||||
public UUID getSubject() {
|
|
||||||
return subject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSubject(UUID subject) {
|
|
||||||
this.subject = subject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String _name = "name";
|
|
||||||
@LogSensitive
|
|
||||||
public String name;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String _scope = "scope";
|
|
||||||
public List<String> scope;
|
|
||||||
|
|
||||||
public List<String> getScope() {
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScope(List<String> scope) {
|
|
||||||
this.scope = scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String _client = "client";
|
|
||||||
public String client;
|
|
||||||
|
|
||||||
public String getClient() {
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClient(String client) {
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String _notBefore = "notBefore";
|
|
||||||
public Instant notBefore;
|
|
||||||
|
|
||||||
public Instant getNotBefore() {
|
|
||||||
return notBefore;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNotBefore(Instant notBefore) {
|
|
||||||
this.notBefore = notBefore;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String _issuedAt = "issuedAt";
|
|
||||||
public Instant issuedAt;
|
|
||||||
|
|
||||||
public Instant getIssuedAt() {
|
|
||||||
return issuedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIssuedAt(Instant issuedAt) {
|
|
||||||
this.issuedAt = issuedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String _authenticatedAt = "authenticatedAt";
|
|
||||||
public Instant authenticatedAt;
|
|
||||||
|
|
||||||
public Instant getAuthenticatedAt() {
|
|
||||||
return authenticatedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAuthenticatedAt(Instant authenticatedAt) {
|
|
||||||
this.authenticatedAt = authenticatedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String _expiresAt = "expiresAt";
|
|
||||||
public Instant expiresAt;
|
|
||||||
|
|
||||||
public Instant getExpiresAt() {
|
|
||||||
return expiresAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExpiresAt(Instant expiresAt) {
|
|
||||||
this.expiresAt = expiresAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String _more = "more";
|
|
||||||
@LogSensitive
|
|
||||||
public Map<String, List<String>> more;
|
|
||||||
|
|
||||||
public Map<String, List<String>> getMore() {
|
|
||||||
return more;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMore(Map<String, List<String>> more) {
|
|
||||||
this.more = more;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static final String _isAuthenticated = "isAuthenticated";
|
|
||||||
private Boolean isAuthenticated;
|
|
||||||
|
|
||||||
public Boolean getIsAuthenticated() {
|
|
||||||
return isAuthenticated;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIsAuthenticated(Boolean authenticated) {
|
|
||||||
isAuthenticated = authenticated;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String _principal = "principal";
|
|
||||||
private PrincipalInfo principal;
|
|
||||||
|
|
||||||
public PrincipalInfo getPrincipal() {
|
|
||||||
return principal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPrincipal(PrincipalInfo principal) {
|
|
||||||
this.principal = principal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String _permissions = "permissions";
|
|
||||||
private List<String> permissions;
|
|
||||||
|
|
||||||
public List<String> getPermissions() {
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPermissions(List<String> permissions) {
|
|
||||||
this.permissions = permissions;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
package gr.cite.annotation.web.model;
|
|
||||||
|
|
||||||
import gr.cite.commons.web.authz.configuration.AuthorizationConfiguration;
|
|
||||||
import gr.cite.commons.web.authz.configuration.Permission;
|
|
||||||
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
|
||||||
import gr.cite.commons.web.oidc.principal.MyPrincipal;
|
|
||||||
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
|
|
||||||
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorKeys;
|
|
||||||
import gr.cite.annotation.common.scope.user.UserScope;
|
|
||||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
|
||||||
import gr.cite.tools.fieldset.FieldSet;
|
|
||||||
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 AccountBuilder {
|
|
||||||
|
|
||||||
private final ClaimExtractor claimExtractor;
|
|
||||||
private final Set<String> excludeMoreClaim;
|
|
||||||
private final AuthorizationConfiguration authorizationConfiguration;
|
|
||||||
private final CurrentPrincipalResolver currentPrincipalResolver;
|
|
||||||
private final UserScope userScope;
|
|
||||||
|
|
||||||
public AccountBuilder(ClaimExtractor claimExtractor, AuthorizationConfiguration authorizationConfiguration, CurrentPrincipalResolver currentPrincipalResolver, UserScope userScope) {
|
|
||||||
this.claimExtractor = claimExtractor;
|
|
||||||
this.authorizationConfiguration = authorizationConfiguration;
|
|
||||||
this.currentPrincipalResolver = currentPrincipalResolver;
|
|
||||||
this.userScope = userScope;
|
|
||||||
this.excludeMoreClaim = Set.of(
|
|
||||||
ClaimExtractorKeys.Subject,
|
|
||||||
ClaimExtractorKeys.Name,
|
|
||||||
ClaimExtractorKeys.Scope,
|
|
||||||
ClaimExtractorKeys.Client,
|
|
||||||
ClaimExtractorKeys.IssuedAt,
|
|
||||||
ClaimExtractorKeys.NotBefore,
|
|
||||||
ClaimExtractorKeys.AuthenticatedAt,
|
|
||||||
ClaimExtractorKeys.ExpiresAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Account build(FieldSet fields, MyPrincipal principal) {
|
|
||||||
Account model = new Account();
|
|
||||||
if (principal == null || !principal.isAuthenticated()) {
|
|
||||||
model.setIsAuthenticated(false);
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
model.setIsAuthenticated(true);
|
|
||||||
|
|
||||||
FieldSet principalFields = fields.extractPrefixed(BaseFieldSet.asIndexerPrefix(Account._principal));
|
|
||||||
if (!principalFields.isEmpty()) model.setPrincipal(new Account.PrincipalInfo());
|
|
||||||
if (principalFields.hasField(Account.PrincipalInfo._subject)) model.getPrincipal().setSubject(this.claimExtractor.subjectUUID(principal));
|
|
||||||
if (principalFields.hasField(Account.PrincipalInfo._userId)) model.getPrincipal().setUserId(this.userScope.getUserIdSafe());
|
|
||||||
if (principalFields.hasField(Account.PrincipalInfo._name)) model.getPrincipal().setName(this.claimExtractor.name(principal));
|
|
||||||
if (principalFields.hasField(Account.PrincipalInfo._scope)) model.getPrincipal().setScope(this.claimExtractor.scope(principal));
|
|
||||||
if (principalFields.hasField(Account.PrincipalInfo._client)) model.getPrincipal().setClient(this.claimExtractor.client(principal));
|
|
||||||
if (principalFields.hasField(Account.PrincipalInfo._issuedAt)) model.getPrincipal().setIssuedAt(this.claimExtractor.issuedAt(principal));
|
|
||||||
if (principalFields.hasField(Account.PrincipalInfo._notBefore)) model.getPrincipal().setNotBefore(this.claimExtractor.notBefore(principal));
|
|
||||||
if (principalFields.hasField(Account.PrincipalInfo._authenticatedAt)) model.getPrincipal().setAuthenticatedAt(this.claimExtractor.authenticatedAt(principal));
|
|
||||||
if (principalFields.hasField(Account.PrincipalInfo._expiresAt)) model.getPrincipal().setExpiresAt(this.claimExtractor.expiresAt(principal));
|
|
||||||
if (principalFields.hasField(Account.PrincipalInfo._more)) {
|
|
||||||
model.getPrincipal().setMore(new HashMap<>());
|
|
||||||
for (String key : this.claimExtractor.knownPublicKeys()) {
|
|
||||||
if (this.excludeMoreClaim.contains(key)) continue;
|
|
||||||
List<String> values = this.claimExtractor.asStrings(principal, key);
|
|
||||||
if (values == null || values.size() == 0) continue;
|
|
||||||
if (!model.getPrincipal().getMore().containsKey(key)) model.getPrincipal().getMore().put(key, new ArrayList<>());
|
|
||||||
model.getPrincipal().getMore().get(key).addAll(values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fields.hasField(Account._permissions)) {
|
|
||||||
List<String> roles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal());
|
|
||||||
Set<String> permissions = authorizationConfiguration.permissionsOfRoles(roles);
|
|
||||||
for (Map.Entry<String, Permission> permissionEntry : authorizationConfiguration.getRawPolicies().entrySet()){
|
|
||||||
if (permissionEntry.getValue().getAllowAuthenticated()){
|
|
||||||
permissions.add(permissionEntry.getKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
model.setPermissions(new ArrayList<>(permissions));
|
|
||||||
}
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package gr.cite.annotation.web.model;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class QueryResult<M> {
|
|
||||||
public QueryResult() { }
|
|
||||||
public QueryResult(List<M> items, long count)
|
|
||||||
{
|
|
||||||
this.items = items;
|
|
||||||
this.count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<M> items;
|
|
||||||
public long count;
|
|
||||||
|
|
||||||
public List<M> getItems() {
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setItems(List<M> items) {
|
|
||||||
this.items = items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCount() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCount(long count) {
|
|
||||||
this.count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static QueryResult<?> Empty()
|
|
||||||
{
|
|
||||||
return new QueryResult<>(new ArrayList<>(), 0L);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.tenant;
|
|
||||||
|
|
||||||
import gr.cite.tools.cache.CacheOptions;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ConfigurationProperties(prefix = "cache.tenant-by-code")
|
|
||||||
public class TenantByCodeCacheOptions extends CacheOptions {
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.tenant;
|
|
||||||
|
|
||||||
import gr.cite.annotation.convention.ConventionService;
|
|
||||||
import gr.cite.annotation.event.TenantTouchedEvent;
|
|
||||||
import gr.cite.tools.cache.CacheService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.event.EventListener;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class TenantByCodeCacheService extends CacheService<TenantByCodeCacheService.TenantByCodeCacheValue> {
|
|
||||||
|
|
||||||
public static class TenantByCodeCacheValue {
|
|
||||||
|
|
||||||
public TenantByCodeCacheValue() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public TenantByCodeCacheValue(String tenantCode, UUID tenantId) {
|
|
||||||
this.tenantCode = tenantCode;
|
|
||||||
this.tenantId = tenantId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String tenantCode;
|
|
||||||
|
|
||||||
public String getTenantCode() {
|
|
||||||
return tenantCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTenantCode(String tenantCode) {
|
|
||||||
this.tenantCode = tenantCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private UUID tenantId;
|
|
||||||
|
|
||||||
public UUID getTenantId() {
|
|
||||||
return tenantId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTenantId(UUID tenantId) {
|
|
||||||
this.tenantId = tenantId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final ConventionService conventionService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public TenantByCodeCacheService(TenantByCodeCacheOptions options, ConventionService conventionService) {
|
|
||||||
super(options);
|
|
||||||
this.conventionService = conventionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener
|
|
||||||
public void handleTenantTouchedEvent(TenantTouchedEvent event) {
|
|
||||||
if (!this.conventionService.isNullOrEmpty(event.getTenantCode()))
|
|
||||||
this.evict(this.buildKey(event.getTenantCode()));
|
|
||||||
if (!this.conventionService.isNullOrEmpty(event.getPreviousTenantCode()))
|
|
||||||
this.evict(this.buildKey(event.getPreviousTenantCode()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<TenantByCodeCacheValue> valueClass() {
|
|
||||||
return TenantByCodeCacheValue.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String keyOf(TenantByCodeCacheValue value) {
|
|
||||||
return this.buildKey(value.getTenantCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String buildKey(String code) {
|
|
||||||
HashMap<String, String> keyParts = new HashMap<>();
|
|
||||||
keyParts.put("$code$", code);
|
|
||||||
return this.generateKey(keyParts);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.tenant;
|
|
||||||
|
|
||||||
import gr.cite.tools.cache.CacheOptions;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ConfigurationProperties(prefix = "cache.tenant-by-id")
|
|
||||||
public class TenantByIdCacheOptions extends CacheOptions {
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.tenant;
|
|
||||||
|
|
||||||
import gr.cite.annotation.convention.ConventionService;
|
|
||||||
import gr.cite.annotation.event.TenantTouchedEvent;
|
|
||||||
import gr.cite.tools.cache.CacheService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.event.EventListener;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class TenantByIdCacheService extends CacheService<TenantByIdCacheService.TenantByIdCacheValue> {
|
|
||||||
|
|
||||||
public static class TenantByIdCacheValue {
|
|
||||||
|
|
||||||
public TenantByIdCacheValue() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public TenantByIdCacheValue(String tenantCode, UUID tenantId) {
|
|
||||||
this.tenantCode = tenantCode;
|
|
||||||
this.tenantId = tenantId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String tenantCode;
|
|
||||||
|
|
||||||
public String getTenantCode() {
|
|
||||||
return tenantCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTenantCode(String tenantCode) {
|
|
||||||
this.tenantCode = tenantCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private UUID tenantId;
|
|
||||||
|
|
||||||
public UUID getTenantId() {
|
|
||||||
return tenantId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTenantId(UUID tenantId) {
|
|
||||||
this.tenantId = tenantId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final ConventionService conventionService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public TenantByIdCacheService(TenantByIdCacheOptions options, ConventionService conventionService) {
|
|
||||||
super(options);
|
|
||||||
this.conventionService = conventionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener
|
|
||||||
public void handleTenantTouchedEvent(TenantTouchedEvent event) {
|
|
||||||
if (!this.conventionService.isNullOrEmpty(event.getTenantCode()))
|
|
||||||
this.evict(this.buildKey(event.getTenantId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<TenantByIdCacheValue> valueClass() {
|
|
||||||
return TenantByIdCacheValue.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String keyOf(TenantByIdCacheValue value) {
|
|
||||||
return this.buildKey(value.getTenantId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String buildKey(UUID id) {
|
|
||||||
HashMap<String, String> keyParts = new HashMap<>();
|
|
||||||
keyParts.put("$tenantId$", id.toString().toLowerCase(Locale.ROOT));
|
|
||||||
return this.generateKey(keyParts);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,189 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.tenant;
|
|
||||||
|
|
||||||
|
|
||||||
import gr.cite.annotation.authorization.ClaimNames;
|
|
||||||
import gr.cite.annotation.authorization.Permission;
|
|
||||||
import gr.cite.annotation.common.enums.IsActive;
|
|
||||||
import gr.cite.annotation.common.scope.tenant.TenantScope;
|
|
||||||
import gr.cite.annotation.common.scope.user.UserScope;
|
|
||||||
import gr.cite.annotation.data.TenantUserEntity;
|
|
||||||
import gr.cite.annotation.data.UserEntity;
|
|
||||||
import gr.cite.annotation.data.tenant.TenantScopedBaseEntity;
|
|
||||||
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
|
|
||||||
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.commons.web.oidc.principal.CurrentPrincipalResolver;
|
|
||||||
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
|
|
||||||
import gr.cite.tools.exception.MyForbiddenException;
|
|
||||||
import gr.cite.tools.logging.LoggerService;
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
|
||||||
import jakarta.persistence.criteria.CriteriaQuery;
|
|
||||||
import jakarta.persistence.criteria.Root;
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.lang.NonNull;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.ui.ModelMap;
|
|
||||||
import org.springframework.web.context.request.ServletWebRequest;
|
|
||||||
import org.springframework.web.context.request.WebRequest;
|
|
||||||
import org.springframework.web.context.request.WebRequestInterceptor;
|
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class TenantInterceptor implements WebRequestInterceptor {
|
|
||||||
|
|
||||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantInterceptor.class));
|
|
||||||
private final TenantScope tenantScope;
|
|
||||||
private final UserScope userScope;
|
|
||||||
private final CurrentPrincipalResolver currentPrincipalResolver;
|
|
||||||
private final ClaimExtractor claimExtractor;
|
|
||||||
private final ApplicationContext applicationContext;
|
|
||||||
private final TenantScopeProperties tenantScopeProperties;
|
|
||||||
private final UserAllowedTenantCacheService userAllowedTenantCacheService;
|
|
||||||
private final ErrorThesaurusProperties errors;
|
|
||||||
private final QueryUtilsService queryUtilsService;
|
|
||||||
@PersistenceContext
|
|
||||||
public EntityManager entityManager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public TenantInterceptor(
|
|
||||||
TenantScope tenantScope,
|
|
||||||
UserScope userScope,
|
|
||||||
CurrentPrincipalResolver currentPrincipalResolver,
|
|
||||||
ClaimExtractor claimExtractor,
|
|
||||||
ApplicationContext applicationContext,
|
|
||||||
TenantScopeProperties tenantScopeProperties,
|
|
||||||
UserAllowedTenantCacheService userAllowedTenantCacheService,
|
|
||||||
ErrorThesaurusProperties errors, QueryUtilsService queryUtilsService) {
|
|
||||||
this.tenantScope = tenantScope;
|
|
||||||
this.userScope = userScope;
|
|
||||||
this.currentPrincipalResolver = currentPrincipalResolver;
|
|
||||||
this.claimExtractor = claimExtractor;
|
|
||||||
this.applicationContext = applicationContext;
|
|
||||||
this.tenantScopeProperties = tenantScopeProperties;
|
|
||||||
this.userAllowedTenantCacheService = userAllowedTenantCacheService;
|
|
||||||
this.errors = errors;
|
|
||||||
this.queryUtilsService = queryUtilsService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void preHandle(@NotNull WebRequest request) throws InvalidApplicationException, InterruptedException {
|
|
||||||
if (!this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) return;
|
|
||||||
if (!this.tenantScope.isMultitenant()) return;
|
|
||||||
|
|
||||||
boolean isAllowedNoTenant = this.applicationContext.getBean(AuthorizationService.class).authorize(Permission.AllowNoTenant);
|
|
||||||
if (tenantScope.isSet() && this.entityManager != null) {
|
|
||||||
List<String> currentPrincipalTenantCodes = this.claimExtractor.asStrings(this.currentPrincipalResolver.currentPrincipal(), ClaimNames.TenantCodesClaimName);
|
|
||||||
if ((currentPrincipalTenantCodes == null || !currentPrincipalTenantCodes.contains(tenantScope.getTenantCode())) && !isAllowedNoTenant) {
|
|
||||||
logger.warn("tenant not allowed {}", this.tenantScope.getTenant());
|
|
||||||
throw new MyForbiddenException(this.errors.getTenantNotAllowed().getCode(), this.errors.getTenantNotAllowed().getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isUserAllowedTenant = false;
|
|
||||||
if (this.tenantScope.isDefaultTenant()){
|
|
||||||
isUserAllowedTenant = true;
|
|
||||||
} else {
|
|
||||||
UserAllowedTenantCacheService.UserAllowedTenantCacheValue cacheValue = this.userAllowedTenantCacheService.lookup(this.userAllowedTenantCacheService.buildKey(this.userScope.getUserId(), this.tenantScope.getTenant()));
|
|
||||||
if (cacheValue != null) {
|
|
||||||
isUserAllowedTenant = cacheValue.isAllowed();
|
|
||||||
} else {
|
|
||||||
isUserAllowedTenant = this.isUserAllowedTenant();
|
|
||||||
this.userAllowedTenantCacheService.put(new UserAllowedTenantCacheService.UserAllowedTenantCacheValue(this.userScope.getUserId(), this.tenantScope.getTenant(), isUserAllowedTenant));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isUserAllowedTenant) {
|
|
||||||
if(!tenantScope.isDefaultTenant()) {
|
|
||||||
this.entityManager
|
|
||||||
.unwrap(Session.class)
|
|
||||||
.enableFilter(TenantScopedBaseEntity.TENANT_FILTER)
|
|
||||||
.setParameter(TenantScopedBaseEntity.TENANT_FILTER_TENANT_PARAM, tenantScope.getTenant().toString());
|
|
||||||
} else {
|
|
||||||
this.entityManager
|
|
||||||
.unwrap(Session.class)
|
|
||||||
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isAllowedNoTenant || this.isWhiteListedEndpoint(request)) {
|
|
||||||
tenantScope.setTenant(null, null);
|
|
||||||
} else {
|
|
||||||
logger.warn("tenant not allowed {}", this.tenantScope.getTenant());
|
|
||||||
throw new MyForbiddenException(this.errors.getTenantNotAllowed().getCode(), this.errors.getTenantNotAllowed().getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!isAllowedNoTenant) {
|
|
||||||
if (!this.isWhiteListedEndpoint(request)) {
|
|
||||||
logger.warn("tenant scope not provided");
|
|
||||||
throw new MyForbiddenException(this.errors.getMissingTenant().getCode(), this.errors.getMissingTenant().getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isWhiteListedEndpoint(WebRequest request) {
|
|
||||||
String servletPath = ((ServletWebRequest) request).getRequest().getServletPath();
|
|
||||||
if (this.tenantScopeProperties.getWhiteListedEndpoints() != null) {
|
|
||||||
for (String whiteListedEndpoint : this.tenantScopeProperties.getWhiteListedEndpoints()) {
|
|
||||||
if (servletPath.toLowerCase(Locale.ROOT).startsWith(whiteListedEndpoint.toLowerCase(Locale.ROOT))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isUserAllowedTenant() throws InvalidApplicationException, InterruptedException {
|
|
||||||
if (userScope.isSet()) {
|
|
||||||
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
|
|
||||||
CriteriaQuery<UserEntity> query = criteriaBuilder.createQuery(UserEntity.class);
|
|
||||||
Root<UserEntity> root = query.from(UserEntity.class);
|
|
||||||
query.where(criteriaBuilder.and(
|
|
||||||
criteriaBuilder.equal(root.get(UserEntity._isActive), IsActive.Active),
|
|
||||||
criteriaBuilder.in(root.get(UserEntity._id)).value(queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(new BuildSubQueryInput.Builder<>(TenantUserEntity.class, UUID.class)
|
|
||||||
.query(query)
|
|
||||||
.criteriaBuilder(criteriaBuilder)
|
|
||||||
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(TenantUserEntity._userId))
|
|
||||||
.filterFunc((subQueryRoot, cb) ->
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return cb.and(
|
|
||||||
criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._tenantId), this.tenantScope.getTenant()),
|
|
||||||
criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._userId), this.userScope.getUserId()),
|
|
||||||
criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._isActive), IsActive.Active)
|
|
||||||
);
|
|
||||||
} catch (InvalidApplicationException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
))
|
|
||||||
)
|
|
||||||
));
|
|
||||||
query.multiselect(root.get(UserEntity._id).alias(UserEntity._id));
|
|
||||||
List<UserEntity> results = this.entityManager.createQuery(query).getResultList();
|
|
||||||
return !results.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postHandle(@NonNull WebRequest request, ModelMap model) {
|
|
||||||
this.tenantScope.setTenant(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterCompletion(@NonNull WebRequest request, Exception ex) {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,184 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.tenant;
|
|
||||||
|
|
||||||
|
|
||||||
import gr.cite.annotation.authorization.ClaimNames;
|
|
||||||
import gr.cite.annotation.common.enums.IsActive;
|
|
||||||
import gr.cite.annotation.common.scope.tenant.TenantScope;
|
|
||||||
import gr.cite.annotation.convention.ConventionService;
|
|
||||||
import gr.cite.annotation.data.TenantEntity;
|
|
||||||
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
|
|
||||||
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
|
||||||
import gr.cite.commons.web.oidc.principal.MyPrincipal;
|
|
||||||
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
|
|
||||||
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorContext;
|
|
||||||
import gr.cite.tools.exception.MyForbiddenException;
|
|
||||||
import gr.cite.tools.logging.LoggerService;
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
|
||||||
import jakarta.persistence.criteria.CriteriaQuery;
|
|
||||||
import jakarta.persistence.criteria.Root;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.lang.NonNull;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.ui.ModelMap;
|
|
||||||
import org.springframework.web.context.request.WebRequest;
|
|
||||||
import org.springframework.web.context.request.WebRequestInterceptor;
|
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class TenantScopeClaimInterceptor implements WebRequestInterceptor {
|
|
||||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantScopeClaimInterceptor.class));
|
|
||||||
private final TenantScope tenantScope;
|
|
||||||
private final ConventionService conventionService;
|
|
||||||
private final TenantScopeProperties tenantScopeProperties;
|
|
||||||
private final ErrorThesaurusProperties errorThesaurusProperties;
|
|
||||||
private final ClaimExtractor claimExtractor;
|
|
||||||
private final CurrentPrincipalResolver currentPrincipalResolver;
|
|
||||||
private final String clientTenantClaimName;
|
|
||||||
private final ClaimExtractorContext claimExtractorContext;
|
|
||||||
private final TenantByCodeCacheService tenantByCodeCacheService;
|
|
||||||
private final TenantByIdCacheService tenantByIdCacheService;
|
|
||||||
@PersistenceContext
|
|
||||||
public EntityManager entityManager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public TenantScopeClaimInterceptor(
|
|
||||||
TenantScope tenantScope,
|
|
||||||
ConventionService conventionService,
|
|
||||||
ClaimExtractor claimExtractor,
|
|
||||||
CurrentPrincipalResolver currentPrincipalResolver,
|
|
||||||
ErrorThesaurusProperties errorThesaurusProperties,
|
|
||||||
TenantScopeProperties tenantScopeProperties,
|
|
||||||
ClaimExtractorContext claimExtractorContext,
|
|
||||||
TenantByCodeCacheService tenantByCodeCacheService,
|
|
||||||
TenantByIdCacheService tenantByIdCacheService
|
|
||||||
) {
|
|
||||||
this.tenantScope = tenantScope;
|
|
||||||
this.conventionService = conventionService;
|
|
||||||
this.currentPrincipalResolver = currentPrincipalResolver;
|
|
||||||
this.claimExtractor = claimExtractor;
|
|
||||||
this.errorThesaurusProperties = errorThesaurusProperties;
|
|
||||||
this.tenantScopeProperties = tenantScopeProperties;
|
|
||||||
this.claimExtractorContext = claimExtractorContext;
|
|
||||||
this.tenantByCodeCacheService = tenantByCodeCacheService;
|
|
||||||
this.tenantByIdCacheService = tenantByIdCacheService;
|
|
||||||
this.clientTenantClaimName = this.tenantScopeProperties.getClientClaimsPrefix() + ClaimNames.TenantClaimName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void preHandle(@NotNull WebRequest request) throws InvalidApplicationException {
|
|
||||||
if (!this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) return;
|
|
||||||
if (!this.tenantScope.isMultitenant()) return;
|
|
||||||
|
|
||||||
MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal();
|
|
||||||
if (principal != null && principal.isAuthenticated() /* principal.Claims.Any() */) {
|
|
||||||
boolean scoped = this.scopeByPrincipal(principal);
|
|
||||||
if (!scoped) scoped = this.scopeByClient(principal);
|
|
||||||
if (!scoped && this.tenantScope.isSet() && this.tenantScopeProperties.getEnforceTrustedTenant())
|
|
||||||
throw new MyForbiddenException(this.errorThesaurusProperties.getMissingTenant().getCode(), this.errorThesaurusProperties.getMissingTenant().getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean scopeByPrincipal(MyPrincipal principal) {
|
|
||||||
String tenantCode = this.claimExtractor.tenantString(principal);
|
|
||||||
if (this.conventionService.isNullOrEmpty(tenantCode)) tenantCode = this.claimExtractor.asString(principal, this.clientTenantClaimName);
|
|
||||||
if (tenantCode == null || this.conventionService.isNullOrEmpty(tenantCode)) return false;
|
|
||||||
|
|
||||||
if (tenantCode.equalsIgnoreCase(this.tenantScope.getDefaultTenantCode())){
|
|
||||||
logger.debug("parsed tenant header and set tenant to default tenant");
|
|
||||||
this.tenantScope.setTenant(null, tenantCode);
|
|
||||||
this.claimExtractorContext.putReplaceParameter(TenantScope.TenantReplaceParameter, tenantCode);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
UUID tenantId = this.conventionService.parseUUIDSafe(tenantCode);
|
|
||||||
if (tenantId == null) {
|
|
||||||
TenantByCodeCacheService.TenantByCodeCacheValue cacheValue = this.tenantByCodeCacheService.lookup(this.tenantByCodeCacheService.buildKey(tenantCode));
|
|
||||||
if (cacheValue != null) {
|
|
||||||
tenantId = cacheValue.getTenantId();
|
|
||||||
} else {
|
|
||||||
tenantId = this.getTenantIdFromDatabase(tenantCode);
|
|
||||||
this.tenantByCodeCacheService.put(new TenantByCodeCacheService.TenantByCodeCacheValue(tenantCode, tenantId));
|
|
||||||
this.tenantByIdCacheService.put(new TenantByIdCacheService.TenantByIdCacheValue(tenantCode, tenantId));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.debug("tenant claim was set to {}", tenantId);
|
|
||||||
TenantByIdCacheService.TenantByIdCacheValue cacheValue = this.tenantByIdCacheService.lookup(this.tenantByIdCacheService.buildKey(tenantId));
|
|
||||||
|
|
||||||
if (cacheValue != null) {
|
|
||||||
tenantCode = cacheValue.getTenantCode();
|
|
||||||
} else {
|
|
||||||
tenantCode = this.getTenantCodeFromDatabase(tenantId);
|
|
||||||
this.tenantByCodeCacheService.put(new TenantByCodeCacheService.TenantByCodeCacheValue(tenantCode, tenantId));
|
|
||||||
this.tenantByIdCacheService.put(new TenantByIdCacheService.TenantByIdCacheValue(tenantCode, tenantId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tenantId != null) {
|
|
||||||
logger.debug("parsed tenant header and set tenant id to {}", tenantId);
|
|
||||||
this.tenantScope.setTenant(tenantId, tenantCode);
|
|
||||||
this.claimExtractorContext.putReplaceParameter(TenantScope.TenantReplaceParameter, tenantCode);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean scopeByClient(MyPrincipal principal) throws InvalidApplicationException {
|
|
||||||
String client = this.claimExtractor.client(principal);
|
|
||||||
|
|
||||||
Boolean isWhiteListed = this.tenantScopeProperties.getWhiteListedClients() != null && !this.conventionService.isNullOrEmpty(client) && this.tenantScopeProperties.getWhiteListedClients().contains(client);
|
|
||||||
logger.debug("client is whitelisted : {}, scope is set: {}, with value {}", isWhiteListed, this.tenantScope.isSet(), (this.tenantScope.isSet() ? this.tenantScope.getTenant() : null));
|
|
||||||
|
|
||||||
return isWhiteListed && this.tenantScope.isSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
private UUID getTenantIdFromDatabase(String tenantCode) {
|
|
||||||
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
|
|
||||||
CriteriaQuery<TenantEntity> query = criteriaBuilder.createQuery(TenantEntity.class);
|
|
||||||
Root<TenantEntity> root = query.from(TenantEntity.class);
|
|
||||||
query = query.where(
|
|
||||||
criteriaBuilder.and(
|
|
||||||
criteriaBuilder.equal(root.get(TenantEntity._code), tenantCode),
|
|
||||||
criteriaBuilder.equal(root.get(TenantEntity._isActive), IsActive.Active)
|
|
||||||
)
|
|
||||||
).multiselect(root.get(TenantEntity._id).alias(TenantEntity._id));
|
|
||||||
List<TenantEntity> results = this.entityManager.createQuery(query).getResultList();
|
|
||||||
if (results.size() == 1) {
|
|
||||||
return results.getFirst().getId();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTenantCodeFromDatabase(UUID tenantId) {
|
|
||||||
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
|
|
||||||
CriteriaQuery<TenantEntity> query = criteriaBuilder.createQuery(TenantEntity.class);
|
|
||||||
Root<TenantEntity> root = query.from(TenantEntity.class);
|
|
||||||
query = query.where(
|
|
||||||
criteriaBuilder.and(
|
|
||||||
criteriaBuilder.equal(root.get(TenantEntity._id), tenantId),
|
|
||||||
criteriaBuilder.equal(root.get(TenantEntity._isActive), IsActive.Active)
|
|
||||||
)
|
|
||||||
).multiselect(root.get(TenantEntity._code).alias(TenantEntity._code));
|
|
||||||
List<TenantEntity> results = this.entityManager.createQuery(query).getResultList();
|
|
||||||
if (results.size() == 1) {
|
|
||||||
return results.getFirst().getCode();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postHandle(@NonNull WebRequest request, ModelMap model) {
|
|
||||||
this.tenantScope.setTenant(null, null);
|
|
||||||
this.claimExtractorContext.removeReplaceParameter(TenantScope.TenantReplaceParameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterCompletion(@NonNull WebRequest request, Exception ex) {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.tenant;
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableConfigurationProperties(TenantScopeProperties.class)
|
|
||||||
public class TenantScopeConfiguration {
|
|
||||||
}
|
|
|
@ -1,146 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.tenant;
|
|
||||||
|
|
||||||
|
|
||||||
import gr.cite.annotation.authorization.ClaimNames;
|
|
||||||
import gr.cite.annotation.common.enums.IsActive;
|
|
||||||
import gr.cite.annotation.common.scope.tenant.TenantScope;
|
|
||||||
import gr.cite.annotation.convention.ConventionService;
|
|
||||||
import gr.cite.annotation.data.TenantEntity;
|
|
||||||
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
|
||||||
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorContext;
|
|
||||||
import gr.cite.tools.logging.LoggerService;
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
|
||||||
import jakarta.persistence.criteria.CriteriaQuery;
|
|
||||||
import jakarta.persistence.criteria.Root;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.lang.NonNull;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.ui.ModelMap;
|
|
||||||
import org.springframework.web.context.request.WebRequest;
|
|
||||||
import org.springframework.web.context.request.WebRequestInterceptor;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class TenantScopeHeaderInterceptor implements WebRequestInterceptor {
|
|
||||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantScopeHeaderInterceptor.class));
|
|
||||||
private final TenantScope tenantScope;
|
|
||||||
private final ConventionService conventionService;
|
|
||||||
private final TenantByCodeCacheService tenantByCodeCacheService;
|
|
||||||
private final TenantByIdCacheService tenantByIdCacheService;
|
|
||||||
private final ClaimExtractorContext claimExtractorContext;
|
|
||||||
private final CurrentPrincipalResolver currentPrincipalResolver;
|
|
||||||
@PersistenceContext
|
|
||||||
public EntityManager entityManager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public TenantScopeHeaderInterceptor(
|
|
||||||
TenantScope tenantScope,
|
|
||||||
ConventionService conventionService,
|
|
||||||
TenantByCodeCacheService tenantByCodeCacheService,
|
|
||||||
TenantByIdCacheService tenantByIdCacheService,
|
|
||||||
ClaimExtractorContext claimExtractorContext,
|
|
||||||
CurrentPrincipalResolver currentPrincipalResolver
|
|
||||||
) {
|
|
||||||
this.tenantScope = tenantScope;
|
|
||||||
this.conventionService = conventionService;
|
|
||||||
this.tenantByCodeCacheService = tenantByCodeCacheService;
|
|
||||||
this.tenantByIdCacheService = tenantByIdCacheService;
|
|
||||||
this.claimExtractorContext = claimExtractorContext;
|
|
||||||
this.currentPrincipalResolver = currentPrincipalResolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void preHandle(@NotNull WebRequest request) {
|
|
||||||
if (!this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) return;
|
|
||||||
if (!this.tenantScope.isMultitenant()) return;
|
|
||||||
|
|
||||||
String tenantCode = request.getHeader(ClaimNames.TenantClaimName);
|
|
||||||
logger.debug("retrieved request tenant header is: {}", tenantCode);
|
|
||||||
if (tenantCode == null || this.conventionService.isNullOrEmpty(tenantCode)) return;
|
|
||||||
|
|
||||||
if (tenantCode.equalsIgnoreCase(this.tenantScope.getDefaultTenantCode())){
|
|
||||||
logger.debug("parsed tenant header and set tenant to default tenant");
|
|
||||||
this.tenantScope.setTenant(null, tenantCode);
|
|
||||||
this.claimExtractorContext.putReplaceParameter(TenantScope.TenantReplaceParameter, tenantCode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UUID tenantId = this.conventionService.parseUUIDSafe(tenantCode);
|
|
||||||
if (tenantId == null) {
|
|
||||||
TenantByCodeCacheService.TenantByCodeCacheValue cacheValue = this.tenantByCodeCacheService.lookup(this.tenantByCodeCacheService.buildKey(tenantCode));
|
|
||||||
if (cacheValue != null) {
|
|
||||||
tenantId = cacheValue.getTenantId();
|
|
||||||
} else {
|
|
||||||
tenantId = this.getTenantIdFromDatabase(tenantCode);
|
|
||||||
this.tenantByCodeCacheService.put(new TenantByCodeCacheService.TenantByCodeCacheValue(tenantCode, tenantId));
|
|
||||||
this.tenantByIdCacheService.put(new TenantByIdCacheService.TenantByIdCacheValue(tenantCode, tenantId));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TenantByIdCacheService.TenantByIdCacheValue cacheValue = this.tenantByIdCacheService.lookup(this.tenantByIdCacheService.buildKey(tenantId));
|
|
||||||
if (cacheValue != null) {
|
|
||||||
tenantCode = cacheValue.getTenantCode();
|
|
||||||
} else {
|
|
||||||
tenantCode = this.getTenantCodeFromDatabase(tenantId);
|
|
||||||
this.tenantByCodeCacheService.put(new TenantByCodeCacheService.TenantByCodeCacheValue(tenantCode, tenantId));
|
|
||||||
this.tenantByIdCacheService.put(new TenantByIdCacheService.TenantByIdCacheValue(tenantCode, tenantId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tenantId != null) {
|
|
||||||
logger.debug("parsed tenant header and set tenant id to {}", tenantId);
|
|
||||||
this.tenantScope.setTenant(tenantId, tenantCode);
|
|
||||||
this.claimExtractorContext.putReplaceParameter(TenantScope.TenantReplaceParameter, tenantCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private UUID getTenantIdFromDatabase(String tenantCode) {
|
|
||||||
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
|
|
||||||
CriteriaQuery<TenantEntity> query = criteriaBuilder.createQuery(TenantEntity.class);
|
|
||||||
Root<TenantEntity> root = query.from(TenantEntity.class);
|
|
||||||
query = query.where(
|
|
||||||
criteriaBuilder.and(
|
|
||||||
criteriaBuilder.equal(root.get(TenantEntity._code), tenantCode),
|
|
||||||
criteriaBuilder.equal(root.get(TenantEntity._isActive), IsActive.Active)
|
|
||||||
)
|
|
||||||
).multiselect(root.get(TenantEntity._id).alias(TenantEntity._id));
|
|
||||||
List<TenantEntity> results = this.entityManager.createQuery(query).getResultList();
|
|
||||||
if (results.size() == 1) {
|
|
||||||
return results.getFirst().getId();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTenantCodeFromDatabase(UUID tenantId) {
|
|
||||||
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
|
|
||||||
CriteriaQuery<TenantEntity> query = criteriaBuilder.createQuery(TenantEntity.class);
|
|
||||||
Root<TenantEntity> root = query.from(TenantEntity.class);
|
|
||||||
query = query.where(
|
|
||||||
criteriaBuilder.and(
|
|
||||||
criteriaBuilder.equal(root.get(TenantEntity._id), tenantId),
|
|
||||||
criteriaBuilder.equal(root.get(TenantEntity._isActive), IsActive.Active)
|
|
||||||
)
|
|
||||||
).multiselect(root.get(TenantEntity._code).alias(TenantEntity._code));
|
|
||||||
List<TenantEntity> results = this.entityManager.createQuery(query).getResultList();
|
|
||||||
if (results.size() == 1) {
|
|
||||||
return results.getFirst().getCode();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postHandle(@NonNull WebRequest request, ModelMap model) {
|
|
||||||
|
|
||||||
this.tenantScope.setTenant(null, null);
|
|
||||||
this.claimExtractorContext.removeReplaceParameter(TenantScope.TenantReplaceParameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterCompletion(@NonNull WebRequest request, Exception ex) {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.tenant;
|
|
||||||
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@ConfigurationProperties(prefix = "tenant.interceptor")
|
|
||||||
public class TenantScopeProperties {
|
|
||||||
|
|
||||||
private String clientClaimsPrefix;
|
|
||||||
public String getClientClaimsPrefix() {
|
|
||||||
return clientClaimsPrefix;
|
|
||||||
}
|
|
||||||
public void setClientClaimsPrefix(String clientClaimsPrefix) {
|
|
||||||
this.clientClaimsPrefix = clientClaimsPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HashSet<String> whiteListedClients;
|
|
||||||
public HashSet<String> getWhiteListedClients() {
|
|
||||||
return whiteListedClients;
|
|
||||||
}
|
|
||||||
public void setWhiteListedClients(HashSet<String> whiteListedClients) {
|
|
||||||
this.whiteListedClients = whiteListedClients;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> whiteListedEndpoints;
|
|
||||||
public List<String> getWhiteListedEndpoints() {
|
|
||||||
return whiteListedEndpoints;
|
|
||||||
}
|
|
||||||
public void setWhiteListedEndpoints(List<String> whiteListedEndpoints) {
|
|
||||||
this.whiteListedEndpoints = whiteListedEndpoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Boolean enforceTrustedTenant;
|
|
||||||
public Boolean getEnforceTrustedTenant() {
|
|
||||||
return enforceTrustedTenant;
|
|
||||||
}
|
|
||||||
public void setEnforceTrustedTenant(Boolean enforceTrustedTenant) {
|
|
||||||
this.enforceTrustedTenant = enforceTrustedTenant;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.tenant;
|
|
||||||
|
|
||||||
import gr.cite.tools.cache.CacheOptions;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ConfigurationProperties(prefix = "cache.user-allowed-tenant")
|
|
||||||
public class UserAllowedTenantCacheOptions extends CacheOptions {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.tenant;
|
|
||||||
|
|
||||||
import gr.cite.annotation.event.UserAddedToTenantEvent;
|
|
||||||
import gr.cite.annotation.event.UserRemovedFromTenantEvent;
|
|
||||||
import gr.cite.tools.cache.CacheService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.event.EventListener;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class UserAllowedTenantCacheService extends CacheService<UserAllowedTenantCacheService.UserAllowedTenantCacheValue> {
|
|
||||||
|
|
||||||
public static class UserAllowedTenantCacheValue {
|
|
||||||
|
|
||||||
public UserAllowedTenantCacheValue() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserAllowedTenantCacheValue(UUID userId, UUID tenantId, boolean isAllowed) {
|
|
||||||
this.userId = userId;
|
|
||||||
this.tenantId = tenantId;
|
|
||||||
this.isAllowed = isAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private UUID userId;
|
|
||||||
|
|
||||||
public UUID getUserId() {
|
|
||||||
return userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserId(UUID userId) {
|
|
||||||
this.userId = userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private UUID tenantId;
|
|
||||||
|
|
||||||
public UUID getTenantId() {
|
|
||||||
return tenantId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTenantId(UUID tenantId) {
|
|
||||||
this.tenantId = tenantId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isAllowed;
|
|
||||||
|
|
||||||
public boolean isAllowed() {
|
|
||||||
return isAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAllowed(boolean allowed) {
|
|
||||||
isAllowed = allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public UserAllowedTenantCacheService(UserAllowedTenantCacheOptions options) {
|
|
||||||
super(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener
|
|
||||||
public void handleUserRemovedFromTenantEvent(UserRemovedFromTenantEvent event) {
|
|
||||||
this.evict(this.buildKey(event.getUserId(), event.getTenantId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener
|
|
||||||
public void handleUserAddedToTenantEvent(UserAddedToTenantEvent event) {
|
|
||||||
this.evict(this.buildKey(event.getUserId(), event.getTenantId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<UserAllowedTenantCacheValue> valueClass() {
|
|
||||||
return UserAllowedTenantCacheValue.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String keyOf(UserAllowedTenantCacheValue value) {
|
|
||||||
return this.buildKey(value.getUserId(), value.getTenantId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String buildKey(UUID userId, UUID tenantId) {
|
|
||||||
HashMap<String, String> keyParts = new HashMap<>();
|
|
||||||
keyParts.put("$user_id$", userId.toString().toLowerCase(Locale.ROOT));
|
|
||||||
keyParts.put("$tenant_id$", tenantId.toString().toLowerCase(Locale.ROOT));
|
|
||||||
return this.generateKey(keyParts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.user;
|
|
||||||
|
|
||||||
|
|
||||||
import gr.cite.annotation.common.scope.user.UserScope;
|
|
||||||
import gr.cite.annotation.data.UserCredentialEntity;
|
|
||||||
import gr.cite.annotation.model.UserCredential;
|
|
||||||
import gr.cite.annotation.query.UserCredentialQuery;
|
|
||||||
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
|
|
||||||
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
|
|
||||||
import gr.cite.tools.data.query.QueryFactory;
|
|
||||||
import gr.cite.tools.exception.MyForbiddenException;
|
|
||||||
import gr.cite.tools.fieldset.BaseFieldSet;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.lang.NonNull;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.ui.ModelMap;
|
|
||||||
import org.springframework.web.context.request.WebRequest;
|
|
||||||
import org.springframework.web.context.request.WebRequestInterceptor;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class UserInterceptor implements WebRequestInterceptor {
|
|
||||||
private final UserScope userScope;
|
|
||||||
private final ClaimExtractor claimExtractor;
|
|
||||||
private final CurrentPrincipalResolver currentPrincipalResolver;
|
|
||||||
private final UserInterceptorCacheService userInterceptorCacheService;
|
|
||||||
private final QueryFactory queryFactory;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public UserInterceptor(
|
|
||||||
UserScope userScope,
|
|
||||||
ClaimExtractor claimExtractor,
|
|
||||||
CurrentPrincipalResolver currentPrincipalResolver,
|
|
||||||
UserInterceptorCacheService userInterceptorCacheService,
|
|
||||||
QueryFactory queryFactory) {
|
|
||||||
this.userScope = userScope;
|
|
||||||
this.currentPrincipalResolver = currentPrincipalResolver;
|
|
||||||
this.claimExtractor = claimExtractor;
|
|
||||||
this.userInterceptorCacheService = userInterceptorCacheService;
|
|
||||||
this.queryFactory = queryFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void preHandle(@NotNull WebRequest request) {
|
|
||||||
UUID userId = null;
|
|
||||||
if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) {
|
|
||||||
String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal());
|
|
||||||
if (subjectId == null || subjectId.isBlank()) throw new MyForbiddenException("Empty subjects not allowed");
|
|
||||||
|
|
||||||
UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId));
|
|
||||||
if (cacheValue != null) {
|
|
||||||
userId = cacheValue.getUserId();
|
|
||||||
} else {
|
|
||||||
userId = this.findExistingUserFromDb(subjectId);
|
|
||||||
if (userId != null) {
|
|
||||||
cacheValue = new UserInterceptorCacheService.UserInterceptorCacheValue(subjectId, userId);
|
|
||||||
this.userInterceptorCacheService.put(cacheValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.userScope.setUserId(userId);
|
|
||||||
}
|
|
||||||
private UUID findExistingUserFromDb(String subjectId) {
|
|
||||||
UserCredentialEntity userCredential = this.queryFactory.query(UserCredentialQuery.class).externalIds(subjectId).firstAs(new BaseFieldSet().ensure(UserCredential._user));
|
|
||||||
if (userCredential != null) {
|
|
||||||
return userCredential.getUserId();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void postHandle(@NonNull WebRequest request, ModelMap model) {
|
|
||||||
this.userScope.setUserId(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterCompletion(@NonNull WebRequest request, Exception ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.user;
|
|
||||||
|
|
||||||
import gr.cite.tools.cache.CacheOptions;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ConfigurationProperties(prefix = "cache.user-by-subject-id")
|
|
||||||
public class UserInterceptorCacheOptions extends CacheOptions {
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
package gr.cite.annotation.web.scope.user;
|
|
||||||
|
|
||||||
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.UUID;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> {
|
|
||||||
|
|
||||||
public static class UserInterceptorCacheValue {
|
|
||||||
|
|
||||||
public UserInterceptorCacheValue() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserInterceptorCacheValue(String subjectId, UUID userId) {
|
|
||||||
this.subjectId = subjectId;
|
|
||||||
this.userId = userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getSubjectId() {
|
|
||||||
return subjectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSubjectId(String subjectId) {
|
|
||||||
this.subjectId = subjectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String subjectId;
|
|
||||||
private UUID userId;
|
|
||||||
|
|
||||||
public UUID getUserId() {
|
|
||||||
return userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserId(UUID userId) {
|
|
||||||
this.userId = userId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) {
|
|
||||||
super(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<UserInterceptorCacheValue> valueClass() {
|
|
||||||
return UserInterceptorCacheValue.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String keyOf(UserInterceptorCacheValue value) {
|
|
||||||
return this.buildKey(value.getSubjectId());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String buildKey(String subject) {
|
|
||||||
HashMap<String, String> keyParts = new HashMap<>();
|
|
||||||
keyParts.put("$subject$", subject);
|
|
||||||
return this.generateKey(keyParts);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
spring:
|
|
||||||
jackson:
|
|
||||||
default-property-inclusion: non_null
|
|
||||||
config:
|
|
||||||
import: optional:classpath:config/app.env[.properties], optional:file:../config/app.env[.properties],
|
|
||||||
optional:classpath:config/db.yml[.yml], optional:classpath:config/db-${spring.profiles.active}.yml[.yml], optional:file:../config/db-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/permissions.yml[.yml], optional:classpath:config/permissions-${spring.profiles.active}.yml[.yml], optional:file:../config/permissions-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/errors.yml[.yml], optional:classpath:config/errors-${spring.profiles.active}.yml[.yml], optional:file:../config/errors-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/security.yml[.yml], optional:classpath:config/security-${spring.profiles.active}.yml[.yml], optional:file:../config/security-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/server.yml[.yml], optional:classpath:config/server-${spring.profiles.active}.yml[.yml], optional:file:../config/server-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/logging.yml[.yml], optional:classpath:config/logging-${spring.profiles.active}.yml[.yml], optional:file:../config/logging-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/idpclaims.yml[.yml], optional:classpath:config/idpclaims-${spring.profiles.active}.yml[.yml], optional:file:../config/idpclaims-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/cache.yml[.yml], optional:classpath:config/cache-${spring.profiles.active}.yml[.yml], optional:file:../config/cache-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/tenant.yml[.yml], optional:classpath:config/tenant-${spring.profiles.active}.yml[.yml], optional:file:../config/tenant-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/locale.yml[.yml], optional:classpath:config/locale-${spring.profiles.active}.yml[.yml], optional:file:../config/locale-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/cors.yml[.yml], optional:classpath:config/cors-${spring.profiles.active}.yml[.yml], optional:file:../config/cors-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/queue.yml[.yml], optional:classpath:config/queue-${spring.profiles.active}.yml[.yml], optional:file:../config/queue-${spring.profiles.active}.yml[.yml],
|
|
||||||
optional:classpath:config/cipher.yml[.yml], optional:classpath:config/cipher-${spring.profiles.active}.yml[.yml], optional:file:../config/cipher-${spring.profiles.active}.yml[.yml]
|
|
|
@ -1,59 +0,0 @@
|
||||||
cache:
|
|
||||||
manager:
|
|
||||||
fallbackToNoOpCache: true
|
|
||||||
caffeineCaches:
|
|
||||||
- names: [ apikey ]
|
|
||||||
allowNullValues: true
|
|
||||||
initialCapacity: 100
|
|
||||||
maximumSize: 500
|
|
||||||
enableRecordStats: false
|
|
||||||
expireAfterWriteSeconds: 600
|
|
||||||
- names: [ tenantByCode ]
|
|
||||||
allowNullValues: true
|
|
||||||
initialCapacity: 100
|
|
||||||
maximumSize: 500
|
|
||||||
enableRecordStats: false
|
|
||||||
expireAfterWriteSeconds: 600
|
|
||||||
- names: [ tenantById ]
|
|
||||||
allowNullValues: true
|
|
||||||
initialCapacity: 100
|
|
||||||
maximumSize: 500
|
|
||||||
enableRecordStats: false
|
|
||||||
expireAfterWriteSeconds: 600
|
|
||||||
- names: [ userBySubjectId ]
|
|
||||||
allowNullValues: true
|
|
||||||
initialCapacity: 100
|
|
||||||
maximumSize: 500
|
|
||||||
enableRecordStats: false
|
|
||||||
expireAfterWriteSeconds: 320
|
|
||||||
- names: [ userAccessTenant ]
|
|
||||||
allowNullValues: true
|
|
||||||
initialCapacity: 100
|
|
||||||
maximumSize: 500
|
|
||||||
enableRecordStats: false
|
|
||||||
expireAfterWriteSeconds: 320
|
|
||||||
- names: [ "affiliation" ]
|
|
||||||
allowNullValues: true
|
|
||||||
initialCapacity: 100
|
|
||||||
maximumSize: 5000
|
|
||||||
enableRecordStats: false
|
|
||||||
expireAfterWriteSeconds: 20
|
|
||||||
mapCaches:
|
|
||||||
apiKey:
|
|
||||||
name: apikey
|
|
||||||
keyPattern: ant_resolve_$keyhash$:v0
|
|
||||||
userBySubjectId:
|
|
||||||
name: userBySubjectId
|
|
||||||
keyPattern: ant_user_by_subject_$subject$:v0
|
|
||||||
tenantByCode:
|
|
||||||
name: tenantByCode
|
|
||||||
keyPattern: ant_tenant_by_code_$code$:v0
|
|
||||||
tenantById:
|
|
||||||
name: tenantById
|
|
||||||
keyPattern: ant_tenant_by_id_$tenantId$:v0
|
|
||||||
userAllowedTenant:
|
|
||||||
name: userAccessTenant
|
|
||||||
keyPattern: ant_user_access_tenant_$user_id$_$tenant_id$:v0
|
|
||||||
affiliation:
|
|
||||||
name: affiliation
|
|
||||||
keyPattern: ant_affiliation_$entity$_$user$_$type$:v0
|
|
|
@ -1,35 +0,0 @@
|
||||||
cipher-profiles:
|
|
||||||
profile-map:
|
|
||||||
configuration-profile-name: "configuration"
|
|
||||||
queue-profile-name: "queue"
|
|
||||||
notification-profile-name: "queue"
|
|
||||||
|
|
||||||
cipher:
|
|
||||||
# salted-hash:
|
|
||||||
# default-o: null
|
|
||||||
# options: null
|
|
||||||
symetric-encryption:
|
|
||||||
default-o: null
|
|
||||||
options:
|
|
||||||
configuration:
|
|
||||||
aes:
|
|
||||||
key: ${CIPHER_SYMETRIC_ENCRYPTION_CONFIGURATION_AES_KEY:}
|
|
||||||
iv: ${CIPHER_SYMETRIC_ENCRYPTION_CONFIGURATION_AES_IV:}
|
|
||||||
queue:
|
|
||||||
aes:
|
|
||||||
key: ${CIPHER_SYMETRIC_ENCRYPTION_QUEUE_AES_KEY:}
|
|
||||||
iv: ${CIPHER_SYMETRIC_ENCRYPTION_QUEUE_AES_IV:}
|
|
||||||
masking:
|
|
||||||
default: null
|
|
||||||
options:
|
|
||||||
configuration:
|
|
||||||
character: "*"
|
|
||||||
clear-begining: 2
|
|
||||||
clear-ending: 4
|
|
||||||
at-least-percentage: 70
|
|
||||||
digital-signature:
|
|
||||||
default: null
|
|
||||||
options:
|
|
||||||
configuration:
|
|
||||||
certificate-path: null
|
|
||||||
certificate-password: null
|
|
|
@ -1,3 +0,0 @@
|
||||||
web:
|
|
||||||
cors:
|
|
||||||
allowed-origins: [ http://localhost, http://localhost:4200 ]
|
|
|
@ -1,7 +0,0 @@
|
||||||
web:
|
|
||||||
cors:
|
|
||||||
enabled: true
|
|
||||||
allowed-methods: [ HEAD, GET, POST, PUT, DELETE, PATCH ]
|
|
||||||
allowed-headers: [ Authorization, Cache-Control, Content-Type, Content-Disposition, x-tenant ]
|
|
||||||
exposed-headers: [ Authorization, Cache-Control, Content-Type, Content-Disposition ]
|
|
||||||
allow-credentials: false
|
|
|
@ -1,10 +0,0 @@
|
||||||
spring:
|
|
||||||
datasource:
|
|
||||||
maxIdle: 10
|
|
||||||
minIdle: 5
|
|
||||||
maxActive: 10
|
|
||||||
jpa:
|
|
||||||
show-sql: true
|
|
||||||
properties:
|
|
||||||
hibernate:
|
|
||||||
format_sql: false
|
|
|
@ -1,28 +0,0 @@
|
||||||
spring:
|
|
||||||
jpa:
|
|
||||||
properties:
|
|
||||||
org:
|
|
||||||
hibernate:
|
|
||||||
flushMode: MANUAL
|
|
||||||
hibernate:
|
|
||||||
globally_quoted_identifiers: true
|
|
||||||
ddl-auto: validate
|
|
||||||
dialect: org.hibernate.dialect.PostgreSQLDialect
|
|
||||||
hibernate:
|
|
||||||
naming:
|
|
||||||
physical-strategy: gr.cite.annotation.data.namingstrategy.PrefixPhysicalNamingStrategy
|
|
||||||
implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
|
|
||||||
datasource:
|
|
||||||
url: ${DB_CONNECTION_STRING}
|
|
||||||
username: ${DB_USER}
|
|
||||||
password: ${DB_PASSWORD}
|
|
||||||
driver-class-name: org.postgresql.Driver
|
|
||||||
hikari:
|
|
||||||
connection-timeout: 30000
|
|
||||||
minimum-idle: 3
|
|
||||||
maximum-pool-size: 10
|
|
||||||
idle-timeout: 600000
|
|
||||||
max-lifetime: 1800000
|
|
||||||
|
|
||||||
naming-strategy:
|
|
||||||
prefix: ant_
|
|
|
@ -1,49 +0,0 @@
|
||||||
error-thesaurus:
|
|
||||||
hash-conflict:
|
|
||||||
code: 100
|
|
||||||
message: there is a hash conflict for the item modified. please reload to get the latest changes
|
|
||||||
forbidden:
|
|
||||||
code: 101
|
|
||||||
message: insufficient rights
|
|
||||||
system-error:
|
|
||||||
code: 102
|
|
||||||
message: an unexpected system error occurred
|
|
||||||
missing-tenant:
|
|
||||||
code: 103
|
|
||||||
message: tenant scope not provided
|
|
||||||
invalid-api-key:
|
|
||||||
code: 104
|
|
||||||
message: provided APIKey not valid
|
|
||||||
stale-api-key:
|
|
||||||
code: 105
|
|
||||||
message: there was a problem authorizing you with your API key. Please try again. Contact the system administrator if the problem persists
|
|
||||||
model-validation:
|
|
||||||
code: 106
|
|
||||||
message: validation error
|
|
||||||
sensitive-info:
|
|
||||||
code: 107
|
|
||||||
message: you are attempting to access sensitive information. please don't do that
|
|
||||||
non-person-principal:
|
|
||||||
code: 108
|
|
||||||
message: the operation is available only to person users
|
|
||||||
blocking-consent:
|
|
||||||
code: 113
|
|
||||||
message: user consents are not sufficient to complete the operation
|
|
||||||
single-tenant-configuration-per-type-supported:
|
|
||||||
code: 116
|
|
||||||
message: a single tenant configuration entry per config type is supported
|
|
||||||
incompatible-tenant-configuration-types:
|
|
||||||
code: 117
|
|
||||||
message: the provided tenant configuration type is incompatible
|
|
||||||
missing-totp-token:
|
|
||||||
code: 118
|
|
||||||
message: totp token not provided
|
|
||||||
overlapping-tenant-configuration-notifier-list:
|
|
||||||
code: 119
|
|
||||||
message: Overlapping Tenant Configuration Notifier List
|
|
||||||
tenant-not-allowed:
|
|
||||||
code: 113
|
|
||||||
message: tenant not allowed
|
|
||||||
tenant-tampering:
|
|
||||||
code: 123
|
|
||||||
message: Tenant tampering
|
|
|
@ -1,58 +0,0 @@
|
||||||
idpclient:
|
|
||||||
claims:
|
|
||||||
mapping:
|
|
||||||
Subject:
|
|
||||||
- type: sub
|
|
||||||
Name:
|
|
||||||
- type: name
|
|
||||||
Client:
|
|
||||||
- type: client_id
|
|
||||||
AuthenticationMethod:
|
|
||||||
- type: amr
|
|
||||||
NotBefore:
|
|
||||||
- type: nbf
|
|
||||||
AuthenticatedAt:
|
|
||||||
- type: auth_time
|
|
||||||
ExpiresAt:
|
|
||||||
- type: exp
|
|
||||||
Email:
|
|
||||||
- type: email
|
|
||||||
Roles:
|
|
||||||
- type: resource_access
|
|
||||||
path: dmp_web.roles
|
|
||||||
- type: tenant_roles
|
|
||||||
filterBy: "(.*):::TenantCode::"
|
|
||||||
extractByExpression: "(.*):(.*)"
|
|
||||||
extractExpressionValue: "[[g1]]"
|
|
||||||
GlobalRoles:
|
|
||||||
- type: resource_access
|
|
||||||
path: dmp_web.roles
|
|
||||||
TenantRoles:
|
|
||||||
- type: tenant_roles
|
|
||||||
filterBy: "(.*):::TenantCode::"
|
|
||||||
extractByExpression: "(.*):(.*)"
|
|
||||||
extractExpressionValue: "[[g1]]"
|
|
||||||
Scope:
|
|
||||||
- type: scope
|
|
||||||
AccessToken:
|
|
||||||
- type: x-access-token
|
|
||||||
visibility: SENSITIVE
|
|
||||||
Tenant:
|
|
||||||
- type: x-tenant
|
|
||||||
IssuedAt:
|
|
||||||
- type: iat
|
|
||||||
Issuer:
|
|
||||||
- type: iss
|
|
||||||
Audience:
|
|
||||||
- type: aud
|
|
||||||
TokenType:
|
|
||||||
- type: typ
|
|
||||||
AuthorizedParty:
|
|
||||||
- type: azp
|
|
||||||
Authorities:
|
|
||||||
- type: authorities
|
|
||||||
TenantCodes:
|
|
||||||
- type: tenant_roles
|
|
||||||
filterBy: "(.*):(.*)"
|
|
||||||
extractByExpression: "(.*):(.*)"
|
|
||||||
extractExpressionValue: "[[g2]]"
|
|
|
@ -1,4 +0,0 @@
|
||||||
locale:
|
|
||||||
timezone: UTC
|
|
||||||
language: en
|
|
||||||
culture: en-US
|
|
|
@ -1,2 +0,0 @@
|
||||||
logging:
|
|
||||||
config: classpath:logging/logback-dev.xml
|
|
|
@ -1,35 +0,0 @@
|
||||||
logging:
|
|
||||||
context:
|
|
||||||
request:
|
|
||||||
requestIdKey: req.id
|
|
||||||
requestRemoteHostKey: req.remoteHost
|
|
||||||
requestUriKey: req.requestURI
|
|
||||||
requestQueryStringKey: req.queryString
|
|
||||||
requestUrlKey : req.requestURL
|
|
||||||
requestMethodKey: req.method
|
|
||||||
requestUserAgentKey: req.userAgent
|
|
||||||
requestForwardedForKey: req.xForwardedFor
|
|
||||||
requestSchemeKey: req.scheme
|
|
||||||
requestRemoteAddressKey: req.remoteAddr
|
|
||||||
requestRemotePortKey: req.remotePort
|
|
||||||
requestRemoteUserKey: req.remoteUser
|
|
||||||
principal:
|
|
||||||
subjectKey: usr.subject
|
|
||||||
nameKey: usr.name
|
|
||||||
clientKey: usr.client
|
|
||||||
audit:
|
|
||||||
enable: true
|
|
||||||
requestRemoteHostKey: req.remoteHost
|
|
||||||
requestUriKey: req.requestURI
|
|
||||||
requestQueryStringKey: req.queryString
|
|
||||||
requestUrlKey : req.requestURL
|
|
||||||
requestMethodKey: req.method
|
|
||||||
requestUserAgentKey: req.userAgent
|
|
||||||
requestForwardedForKey: req.xForwardedFor
|
|
||||||
requestSchemeKey: req.scheme
|
|
||||||
requestRemoteAddressKey: req.remoteAddr
|
|
||||||
requestRemotePortKey: req.remotePort
|
|
||||||
requestRemoteUserKey: req.remoteUser
|
|
||||||
principalSubjectKey: usr.subject
|
|
||||||
principalNameKey: usr.name
|
|
||||||
principalClientKey: usr.client
|
|
|
@ -1,99 +0,0 @@
|
||||||
permissions:
|
|
||||||
policies:
|
|
||||||
DeferredAffiliation:
|
|
||||||
roles:
|
|
||||||
- TenantAdmin
|
|
||||||
- TenantUser
|
|
||||||
- TenantManager
|
|
||||||
- TenantDescriptionTemplateEditor
|
|
||||||
clients: [ ]
|
|
||||||
allowAnonymous: false
|
|
||||||
allowAuthenticated: false
|
|
||||||
# Tenants
|
|
||||||
BrowseTenant:
|
|
||||||
roles:
|
|
||||||
- Admin
|
|
||||||
clients: [ ]
|
|
||||||
allowAnonymous: false
|
|
||||||
allowAuthenticated: false
|
|
||||||
EditTenant:
|
|
||||||
roles:
|
|
||||||
- Admin
|
|
||||||
clients: [ "opendmp-api-dev" ]
|
|
||||||
allowAnonymous: false
|
|
||||||
allowAuthenticated: false
|
|
||||||
DeleteTenant:
|
|
||||||
roles:
|
|
||||||
- Admin
|
|
||||||
claims: [ ]
|
|
||||||
clients: [ "opendmp-api-dev" ]
|
|
||||||
allowAnonymous: false
|
|
||||||
allowAuthenticated: false
|
|
||||||
AllowNoTenant:
|
|
||||||
roles:
|
|
||||||
- Admin
|
|
||||||
claims: [ ]
|
|
||||||
clients: [ ]
|
|
||||||
allowAnonymous: false
|
|
||||||
allowAuthenticated: false
|
|
||||||
# Users
|
|
||||||
BrowseUser:
|
|
||||||
roles:
|
|
||||||
- TenantAdmin
|
|
||||||
clients: [ ]
|
|
||||||
allowAnonymous: true
|
|
||||||
allowAuthenticated: false
|
|
||||||
EditUser:
|
|
||||||
roles:
|
|
||||||
- TenantAdmin
|
|
||||||
clients: [ "opendmp-api-dev" ]
|
|
||||||
allowAnonymous: false
|
|
||||||
allowAuthenticated: false
|
|
||||||
DeleteUser:
|
|
||||||
roles:
|
|
||||||
- TenantAdmin
|
|
||||||
claims: [ ]
|
|
||||||
clients: [ "opendmp-api-dev" ]
|
|
||||||
allowAnonymous: false
|
|
||||||
allowAuthenticated: false
|
|
||||||
#Annotation
|
|
||||||
BrowseAnnotation:
|
|
||||||
roles:
|
|
||||||
- TenantAdmin
|
|
||||||
entityAffiliated: true
|
|
||||||
clients: [ ]
|
|
||||||
allowAnonymous: true
|
|
||||||
allowAuthenticated: false
|
|
||||||
NewAnnotation:
|
|
||||||
roles:
|
|
||||||
- TenantAdmin
|
|
||||||
entityAffiliated: true
|
|
||||||
clients: [ ]
|
|
||||||
allowAnonymous: true
|
|
||||||
allowAuthenticated: false
|
|
||||||
EditAnnotation:
|
|
||||||
roles:
|
|
||||||
- TenantAdmin
|
|
||||||
clients: [ ]
|
|
||||||
allowAnonymous: true
|
|
||||||
allowAuthenticated: false
|
|
||||||
DeleteAnnotation:
|
|
||||||
roles:
|
|
||||||
- TenantAdmin
|
|
||||||
entityAffiliated: false
|
|
||||||
clients: [ ]
|
|
||||||
allowAnonymous: false
|
|
||||||
allowAuthenticated: false
|
|
||||||
#Tenant Configuration
|
|
||||||
BrowseTenantConfiguration:
|
|
||||||
roles:
|
|
||||||
- TenantAdmin
|
|
||||||
clients: [ ]
|
|
||||||
allowAnonymous: false
|
|
||||||
allowAuthenticated: false
|
|
||||||
EditTenantConfiguration:
|
|
||||||
roles:
|
|
||||||
- TenantAdmin
|
|
||||||
clients: [ ]
|
|
||||||
allowAnonymous: false
|
|
||||||
allowAuthenticated: false
|
|
|
@ -1,21 +0,0 @@
|
||||||
queue:
|
|
||||||
rabbitmq:
|
|
||||||
enable: true
|
|
||||||
durable: true
|
|
||||||
queue: cite_dmp_devel_annotation_inbox_queue
|
|
||||||
exchange: cite_dmp_devel_queue
|
|
||||||
listenerEnabled: true
|
|
||||||
publisherEnabled: true
|
|
||||||
task:
|
|
||||||
publisher:
|
|
||||||
enable: true
|
|
||||||
options:
|
|
||||||
exchange: cite_dmp_devel_queue
|
|
||||||
rabbitmq:
|
|
||||||
enable: true
|
|
||||||
listener:
|
|
||||||
enable: true
|
|
||||||
options:
|
|
||||||
exchange: cite_dmp_devel_queue
|
|
||||||
rabbitmq:
|
|
||||||
enable: true
|
|
|
@ -1,54 +0,0 @@
|
||||||
spring:
|
|
||||||
rabbitmq:
|
|
||||||
host: ${RABBIT_HOST}
|
|
||||||
port: ${RABBIT_PORT}
|
|
||||||
username: ${RABBIT_USER}
|
|
||||||
password: ${RABBIT_PASS}
|
|
||||||
ssl:
|
|
||||||
enabled: false
|
|
||||||
queue:
|
|
||||||
rabbitmq:
|
|
||||||
enable: false
|
|
||||||
appId: ${QUEUE_APP_ID}
|
|
||||||
durable: null
|
|
||||||
queue: null
|
|
||||||
exchange: null
|
|
||||||
listenerEnabled: true
|
|
||||||
publisherEnabled: true
|
|
||||||
#TODO
|
|
||||||
connection-recovery:
|
|
||||||
enable: true
|
|
||||||
network-recovery-interval: 5000
|
|
||||||
unreachable-recovery-interval: 5000
|
|
||||||
task:
|
|
||||||
publisher:
|
|
||||||
enable: false
|
|
||||||
options:
|
|
||||||
exchange: null
|
|
||||||
rabbitmq:
|
|
||||||
enable: false
|
|
||||||
interval-seconds: 30
|
|
||||||
options:
|
|
||||||
retry-threashold: 100
|
|
||||||
retry-delay-step-seconds: 300
|
|
||||||
max-retry-delay-seconds: 10800
|
|
||||||
too-old-to-send-seconds: 604800
|
|
||||||
confirm-timeout-seconds: 30
|
|
||||||
listener:
|
|
||||||
enable: false
|
|
||||||
options:
|
|
||||||
exchange: null
|
|
||||||
tenant-removal-topic: tenant.remove
|
|
||||||
tenant-touch-topic: tenant.touch
|
|
||||||
user-removal-topic: user.remove
|
|
||||||
user-touch-topic: user.touch
|
|
||||||
annotation-entities-touch-topic: annotation.entities.touch
|
|
||||||
annotation-entities-removal-topic: annotation.entities.remove
|
|
||||||
rabbitmq:
|
|
||||||
enable: false
|
|
||||||
interval-seconds: 30
|
|
||||||
options:
|
|
||||||
retry-threashold: 100
|
|
||||||
retry-delay-step-seconds: 300
|
|
||||||
max-retry-delay-seconds: 10800
|
|
||||||
too-old-to-send-seconds: 604800
|
|
|
@ -1,6 +0,0 @@
|
||||||
web:
|
|
||||||
security:
|
|
||||||
idp:
|
|
||||||
resource:
|
|
||||||
jwt:
|
|
||||||
audiences: [ "dmp_annotation" ]
|
|
|
@ -1,14 +0,0 @@
|
||||||
web:
|
|
||||||
security:
|
|
||||||
enabled: true
|
|
||||||
authorized-endpoints: [ api ]
|
|
||||||
allowed-endpoints: [ public ]
|
|
||||||
idp:
|
|
||||||
api-key:
|
|
||||||
enabled: false
|
|
||||||
resource:
|
|
||||||
token-type: JWT #| opaque
|
|
||||||
jwt:
|
|
||||||
claims: [ role, x-role ]
|
|
||||||
issuer-uri: ${IDP_ISSUER_URI}
|
|
||||||
validIssuer: ${IDP_ISSUER_URI}
|
|
|
@ -1,2 +0,0 @@
|
||||||
server:
|
|
||||||
forward-headers-strategy: FRAMEWORK
|
|
|
@ -1,13 +0,0 @@
|
||||||
server:
|
|
||||||
port: ${WEB_PORT}
|
|
||||||
forward-headers-strategy: NONE
|
|
||||||
tomcat:
|
|
||||||
threads:
|
|
||||||
max: 20
|
|
||||||
max-connections: 10000
|
|
||||||
|
|
||||||
spring:
|
|
||||||
servlet:
|
|
||||||
multipart:
|
|
||||||
max-file-size: 10MB
|
|
||||||
max-request-size: 10MB
|
|
|
@ -1,7 +0,0 @@
|
||||||
tenant:
|
|
||||||
multitenancy:
|
|
||||||
is-multitenant: true
|
|
||||||
default-tenant-code: default
|
|
||||||
interceptor:
|
|
||||||
client-claims-prefix: client_
|
|
||||||
enforce-trusted-tenant: false
|
|
|
@ -1,7 +0,0 @@
|
||||||
tenant:
|
|
||||||
multitenancy:
|
|
||||||
is-multitenant: false
|
|
||||||
interceptor:
|
|
||||||
white-listed-clients: [ ]
|
|
||||||
enforce-trusted-tenant: false
|
|
||||||
white-listed-endpoints: [ '/api/annotation/principal/me' ]
|
|
|
@ -1,61 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration debug="true">
|
|
||||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
|
||||||
<Pattern>%date{ISO8601} [%thread] %-5level %logger{36} [%X{req.id}] - %message%n</Pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<appender name="TROUBLESHOOTING" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
|
||||||
<file>logs/logging.log</file>
|
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
|
||||||
<fileNamePattern>logs/logging.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
|
||||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
|
||||||
<maxFileSize>100MB</maxFileSize>
|
|
||||||
</timeBasedFileNamingAndTriggeringPolicy>
|
|
||||||
<maxHistory>15</maxHistory>
|
|
||||||
</rollingPolicy>
|
|
||||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
|
||||||
<Pattern>%date{ISO8601} [%thread] %-5level %logger{36} [%X{req.id}] - %message%n</Pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<appender name="AUDITING" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
|
||||||
<file>logs/auditing.log</file>
|
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
|
||||||
<fileNamePattern>logs/auditing.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
|
||||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
|
||||||
<maxFileSize>100MB</maxFileSize>
|
|
||||||
</timeBasedFileNamingAndTriggeringPolicy>
|
|
||||||
<maxHistory>15</maxHistory>
|
|
||||||
</rollingPolicy>
|
|
||||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
|
||||||
<Pattern>%date{ISO8601} - %X{req.id} - %message%n</Pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<logger name="org.springframework.web" level="INFO" additivity="false">
|
|
||||||
<appender-ref ref="TROUBLESHOOTING"/>
|
|
||||||
<appender-ref ref="STDOUT"/>
|
|
||||||
</logger>
|
|
||||||
<logger name="org.hibernate" level="INFO" additivity="false">
|
|
||||||
<appender-ref ref="TROUBLESHOOTING"/>
|
|
||||||
<appender-ref ref="STDOUT"/>
|
|
||||||
</logger>
|
|
||||||
<logger name="gr.cite" level="DEBUG" additivity="false">
|
|
||||||
<appender-ref ref="TROUBLESHOOTING"/>
|
|
||||||
<appender-ref ref="STDOUT"/>
|
|
||||||
</logger>
|
|
||||||
<logger name="org.springframework.data.elasticsearch.client.WIRE" level="TRACE" additivity="false">
|
|
||||||
<appender-ref ref="TROUBLESHOOTING"/>
|
|
||||||
<appender-ref ref="STDOUT"/>
|
|
||||||
</logger>
|
|
||||||
<logger name="audit" level="INFO" additivity="false">
|
|
||||||
<appender-ref ref="AUDITING"/>
|
|
||||||
<appender-ref ref="STDOUT"/>
|
|
||||||
</logger>
|
|
||||||
<root level="info">
|
|
||||||
<appender-ref ref="TROUBLESHOOTING"/>
|
|
||||||
<appender-ref ref="STDOUT"/>
|
|
||||||
</root>
|
|
||||||
</configuration>
|
|
|
@ -1,10 +0,0 @@
|
||||||
validation.empty=Value cannot be empty
|
|
||||||
validation.hashempty=Hash must be set
|
|
||||||
validation.lowerthanmin=Value must be larger than {value}
|
|
||||||
validation.largerthanmax=Value must be less than {value}
|
|
||||||
validation.invalidid=Not valid id
|
|
||||||
General_ItemNotFound=Item {0} of type {1} not found
|
|
||||||
Validation_Required={0} is required
|
|
||||||
Validation_OverPosting=Too much info
|
|
||||||
Validation_MaxLength={0} too long
|
|
||||||
Validation_UnexpectedValue=Unexpected value in field {0}
|
|
|
@ -1,6 +0,0 @@
|
||||||
validation.empty=el-Value cannot be empty
|
|
||||||
validation.hashempty=el-Hash must be set
|
|
||||||
validation.lowerthanmin=el-Value must be larger than {value}
|
|
||||||
validation.largerthanmax=el-Value must be less than {value}
|
|
||||||
validation.invalidid=el-Not valid id
|
|
||||||
General_ItemNotFound=el-Item {0} of type {1} not found
|
|
|
@ -1,33 +0,0 @@
|
||||||
HELP.md
|
|
||||||
target/
|
|
||||||
!.mvn/wrapper/maven-wrapper.jar
|
|
||||||
!**/src/main/**/target/
|
|
||||||
!**/src/test/**/target/
|
|
||||||
|
|
||||||
### STS ###
|
|
||||||
.apt_generated
|
|
||||||
.classpath
|
|
||||||
.factorypath
|
|
||||||
.project
|
|
||||||
.settings
|
|
||||||
.springBeans
|
|
||||||
.sts4-cache
|
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
|
||||||
.idea
|
|
||||||
*.iws
|
|
||||||
*.iml
|
|
||||||
*.ipr
|
|
||||||
|
|
||||||
### NetBeans ###
|
|
||||||
/nbproject/private/
|
|
||||||
/nbbuild/
|
|
||||||
/dist/
|
|
||||||
/nbdist/
|
|
||||||
/.nb-gradle/
|
|
||||||
build/
|
|
||||||
!**/src/main/**/build/
|
|
||||||
!**/src/test/**/build/
|
|
||||||
|
|
||||||
### VS Code ###
|
|
||||||
.vscode/
|
|
|
@ -1,101 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>annotation-service-parent</artifactId>
|
|
||||||
<version>${revision}</version>
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>annotation</artifactId>
|
|
||||||
<version>${revision}</version>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<java.version>21</java.version>
|
|
||||||
<maven.compiler.source>21</maven.compiler.source>
|
|
||||||
<maven.compiler.target>21</maven.compiler.target>
|
|
||||||
<revision>1.0.0-SNAPSHOT</revision>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-validation</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-mail</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.poi</groupId>
|
|
||||||
<artifactId>poi</artifactId>
|
|
||||||
<version>5.2.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.poi</groupId>
|
|
||||||
<artifactId>poi-ooxml</artifactId>
|
|
||||||
<version>5.2.2</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>data-tools</artifactId>
|
|
||||||
<version>2.1.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>field-set</artifactId>
|
|
||||||
<version>2.1.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>oidc-authn</artifactId>
|
|
||||||
<version>2.2.1</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>logging</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>oidc-authz</artifactId>
|
|
||||||
<version>2.1.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>exceptions</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>validation</artifactId>
|
|
||||||
<version>3.0.3</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
|
||||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite</groupId>
|
|
||||||
<artifactId>cipher</artifactId>
|
|
||||||
<version>1.0.0</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,59 +0,0 @@
|
||||||
package gr.cite.annotation.audit;
|
|
||||||
|
|
||||||
import gr.cite.tools.logging.EventId;
|
|
||||||
|
|
||||||
public class AuditableAction {
|
|
||||||
// public static final EventId Tenant_Available_Notifiers_Query = new EventId(2006, "Tenant_Available_Notifiers_Query");
|
|
||||||
public static final EventId Principal_Lookup = new EventId(6000, "Principal_Lookup");
|
|
||||||
public static final EventId Tenants_Lookup = new EventId(6001, "Tenants_Lookup");
|
|
||||||
|
|
||||||
// public static final EventId User_Available_Notifiers_Query = new EventId(10004, "User_Available_Notifiers_Query");
|
|
||||||
|
|
||||||
public static final EventId User_Query = new EventId(11000, "User_Query");
|
|
||||||
public static final EventId User_Lookup = new EventId(11001, "User_Lookup");
|
|
||||||
public static final EventId User_Persist = new EventId(11002, "User_Persist");
|
|
||||||
public static final EventId User_Delete = new EventId(11003, "User_Delete");
|
|
||||||
|
|
||||||
public static final EventId Tenant_Query = new EventId(12000, "Tenant_Query");
|
|
||||||
public static final EventId Tenant_Lookup = new EventId(12001, "Tenant_Lookup");
|
|
||||||
public static final EventId Tenant_Persist = new EventId(12002, "Tenant_Persist");
|
|
||||||
public static final EventId Tenant_Delete = new EventId(12003, "Tenant_Delete");
|
|
||||||
|
|
||||||
// public static final EventId Notification_Query = new EventId(19000, "Notification_Query");
|
|
||||||
// public static final EventId Notification_Lookup = new EventId(19001, "Notification_Lookup");
|
|
||||||
// public static final EventId Notification_Persist = new EventId(19002, "Notification_Persist");
|
|
||||||
// public static final EventId Notification_Delete = new EventId(19003, "Notification_Delete");
|
|
||||||
|
|
||||||
// public static final EventId InApp_Notification_Query = new EventId(20000, "InApp_Notification_Query");
|
|
||||||
// public static final EventId InApp_Notification_Lookup = new EventId(20001, "InApp_Notification_Lookup");
|
|
||||||
// public static final EventId InApp_Notification_Persist = new EventId(20002, "InApp_Notification_Persist");
|
|
||||||
// public static final EventId InApp_Notification_Delete = new EventId(20003, "InApp_Notification_Delete");
|
|
||||||
// public static final EventId InApp_Notification_Read = new EventId(20003, "InApp_Notification_Read");
|
|
||||||
// public static final EventId InApp_Notification_Read_All = new EventId(20003, "InApp_Notification_Read_All");
|
|
||||||
|
|
||||||
public static final EventId Tenant_Configuration_Query = new EventId(21000, "Tenant_Configuration_Query");
|
|
||||||
public static final EventId Tenant_Configuration_Lookup = new EventId(21001, "Tenant_Configuration_Lookup");
|
|
||||||
public static final EventId Tenant_Configuration_Persist = new EventId(21002, "Tenant_Configuration_Persist");
|
|
||||||
public static final EventId Tenant_Configuration_Delete = new EventId(21003, "Tenant_Configuration_Delete");
|
|
||||||
|
|
||||||
// public static final EventId User_Notification_Preference_Query = new EventId(22000, "User_Notification_Preference_Query");
|
|
||||||
// public static final EventId User_Notification_Preference_Lookup = new EventId(22001, "User_Notification_Preference_Lookup");
|
|
||||||
// public static final EventId User_Notification_Preference_Persist = new EventId(22002, "User_Notification_Preference_Persist");
|
|
||||||
// public static final EventId User_Notification_Preference_Delete = new EventId(22003, "User_Notification_Preference_Delete");
|
|
||||||
//
|
|
||||||
// public static final EventId Notification_Template_Query = new EventId(23000, "Notification_Template_Query");
|
|
||||||
// public static final EventId Notification_Template_Lookup = new EventId(23001, "Notification_Template_Lookup");
|
|
||||||
// public static final EventId Notification_Template_Persist = new EventId(23002, "Notification_Template_Persist");
|
|
||||||
// public static final EventId Notification_Template_Delete = new EventId(23003, "Notification_Template_Delete");
|
|
||||||
|
|
||||||
public static final EventId Annotation_Query = new EventId(24000, "Annotation_Query");
|
|
||||||
public static final EventId Annotation_Lookup = new EventId(24001, "Annotation_Lookup");
|
|
||||||
public static final EventId Annotation_Persist = new EventId(24002, "Annotation_Persist");
|
|
||||||
public static final EventId Annotation_Delete = new EventId(24003, "Annotation_Delete");
|
|
||||||
|
|
||||||
public static final EventId Entity_User_Query = new EventId(25000, "Entity_User_Query");
|
|
||||||
public static final EventId Entity_User_Lookup = new EventId(25001, "Entity_User_Lookup");
|
|
||||||
public static final EventId Entity_User_Persist = new EventId(25002, "Entity_User_Persist");
|
|
||||||
public static final EventId Entity_User_Delete = new EventId(25003, "Entity_User_Delete");
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
package gr.cite.annotation.authorization;
|
|
||||||
|
|
||||||
import java.util.EnumSet;
|
|
||||||
|
|
||||||
public enum AuthorizationFlags {
|
|
||||||
None, Permission, Associated, Owner;
|
|
||||||
public static final EnumSet<AuthorizationFlags> OwnerOrPermissionAssociated = EnumSet.of(Owner, Permission, Associated);
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package gr.cite.annotation.authorization;
|
|
||||||
|
|
||||||
public class ClaimNames {
|
|
||||||
public static final String ExternalProviderName = "ExternalProviderName";
|
|
||||||
public static final String TenantCodesClaimName = "TenantCodes";
|
|
||||||
public static final String TenantClaimName = "x-tenant";
|
|
||||||
public static final String GlobalRolesClaimName = "GlobalRoles";
|
|
||||||
public static final String TenantRolesClaimName = "TenantRoles";
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
package gr.cite.annotation.authorization;
|
|
||||||
|
|
||||||
import gr.cite.commons.web.authz.policy.AuthorizationRequirement;
|
|
||||||
|
|
||||||
public class OwnedAuthorizationRequirement implements AuthorizationRequirement {
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package gr.cite.annotation.authorization;
|
|
||||||
|
|
||||||
import gr.cite.commons.web.authz.policy.AuthorizationResource;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class OwnedResource extends AuthorizationResource {
|
|
||||||
private List<UUID> userIds;
|
|
||||||
|
|
||||||
public OwnedResource(UUID userId) {
|
|
||||||
this(List.of(userId));
|
|
||||||
}
|
|
||||||
|
|
||||||
public OwnedResource(List<UUID> userIds) {
|
|
||||||
this.userIds = userIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<UUID> getUserIds() {
|
|
||||||
return userIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserIds(List<UUID> userIds) {
|
|
||||||
this.userIds = userIds;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
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";
|
|
||||||
|
|
||||||
|
|
||||||
//Tenant
|
|
||||||
public static String BrowseTenant = "BrowseTenant";
|
|
||||||
public static String EditTenant = "EditTenant";
|
|
||||||
public static String DeleteTenant = "DeleteTenant";
|
|
||||||
public static String AllowNoTenant = "AllowNoTenant";
|
|
||||||
|
|
||||||
//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";
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
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 {
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
|
@ -1,118 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
package gr.cite.annotation.common;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import gr.cite.tools.logging.LoggerService;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class JsonHandlingService {
|
|
||||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(JsonHandlingService.class));
|
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
|
|
||||||
public String toJson(Object item) throws JsonProcessingException {
|
|
||||||
if (item == null) return null;
|
|
||||||
return objectMapper.writeValueAsString(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toJsonSafe(Object item) {
|
|
||||||
if (item == null) return null;
|
|
||||||
try {
|
|
||||||
return objectMapper.writeValueAsString(item);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
logger.error("Json Parsing Error: " + ex.getLocalizedMessage(), ex);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T fromJson(Class<T> type, String json) throws JsonProcessingException {
|
|
||||||
if (json == null) return null;
|
|
||||||
return objectMapper.readValue(json, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T fromJsonSafe(Class<T> type, String json) {
|
|
||||||
if (json == null) return null;
|
|
||||||
try {
|
|
||||||
return objectMapper.readValue(json, type);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
logger.error("Json Parsing Error: " + ex.getLocalizedMessage(), ex);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
package gr.cite.annotation.common;
|
|
||||||
|
|
||||||
public class StringUtils {
|
|
||||||
|
|
||||||
public static Boolean isNullOrEmpty(String string) {
|
|
||||||
return string == null || string.isEmpty();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,117 +0,0 @@
|
||||||
package gr.cite.annotation.common;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import gr.cite.annotation.common.types.xml.XmlSerializable;
|
|
||||||
import jakarta.xml.bind.JAXBContext;
|
|
||||||
import jakarta.xml.bind.JAXBException;
|
|
||||||
import jakarta.xml.bind.Marshaller;
|
|
||||||
import jakarta.xml.bind.Unmarshaller;
|
|
||||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
|
||||||
import org.springframework.context.annotation.Scope;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.transform.OutputKeys;
|
|
||||||
import javax.xml.transform.Transformer;
|
|
||||||
import javax.xml.transform.TransformerException;
|
|
||||||
import javax.xml.transform.TransformerFactory;
|
|
||||||
import javax.xml.transform.dom.DOMSource;
|
|
||||||
import javax.xml.transform.stream.StreamResult;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
|
|
||||||
public class XmlHandlingService {
|
|
||||||
|
|
||||||
public String generateXml(Document doc) throws TransformerException {
|
|
||||||
TransformerFactory tFact = TransformerFactory.newInstance();
|
|
||||||
Transformer trans = tFact.newTransformer();
|
|
||||||
StringWriter writer = new StringWriter();
|
|
||||||
StreamResult result = new StreamResult(writer);
|
|
||||||
DOMSource source = new DOMSource(doc);
|
|
||||||
trans.setOutputProperty(OutputKeys.INDENT, "yes");
|
|
||||||
trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
|
|
||||||
trans.transform(source, result);
|
|
||||||
return writer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toXml(Object item) throws JsonProcessingException, JAXBException, ParserConfigurationException, InvalidApplicationException, TransformerException {
|
|
||||||
if (XmlSerializable.class.isAssignableFrom(item.getClass())){
|
|
||||||
Document document = this.getDocument();
|
|
||||||
if (document == null) throw new InvalidApplicationException("Can not create document");
|
|
||||||
document.appendChild(((XmlSerializable)item).toXml(document));
|
|
||||||
return this.generateXml(document);
|
|
||||||
}
|
|
||||||
|
|
||||||
JAXBContext context = JAXBContext.newInstance(item.getClass());
|
|
||||||
Marshaller marshaller = context.createMarshaller();
|
|
||||||
StringWriter out = new StringWriter();
|
|
||||||
marshaller.marshal(item, out);
|
|
||||||
return out.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toXmlSafe(Object item) {
|
|
||||||
if (item == null) return null;
|
|
||||||
try {
|
|
||||||
return this.toXml(item);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T fromXml(Class<T> type, String xmlString) throws JAXBException, InstantiationException, IllegalAccessException, ParserConfigurationException, IOException, SAXException {
|
|
||||||
if (XmlSerializable.class.isAssignableFrom(type)){
|
|
||||||
XmlSerializable<T> object = (XmlSerializable<T>)type.newInstance();
|
|
||||||
return (T) object.fromXml(this.getDocument(xmlString).getDocumentElement());
|
|
||||||
} else {
|
|
||||||
JAXBContext jaxbContext = JAXBContext.newInstance(type);
|
|
||||||
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
|
|
||||||
|
|
||||||
return (T) jaxbUnmarshaller.unmarshal(new StringReader(xmlString));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> T fromXmlSafe(Class<T> type, String xmlString) {
|
|
||||||
if (xmlString == null) return null;
|
|
||||||
try {
|
|
||||||
return this.fromXml(type, xmlString);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// public <T extends XmlSerializable<T>> T xmlSerializableFromXml(Class<T> type, String xmlString) throws JAXBException, InstantiationException, IllegalAccessException, ParserConfigurationException, IOException, SAXException {
|
|
||||||
// T object = type.newInstance();
|
|
||||||
// return (T) object.fromXml(this.getDocument(xmlString).getDocumentElement());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public <T extends XmlSerializable<T>> T xmlSerializableFromXmlSafe(Class<T> type, String xmlString) {
|
|
||||||
// if (xmlString == null) return null;
|
|
||||||
// try {
|
|
||||||
// return this.xmlSerializableFromXml(type, xmlString);
|
|
||||||
// } catch (Exception ex) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
public Document getDocument(String xml) throws ParserConfigurationException, IOException, SAXException {
|
|
||||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
|
||||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
|
||||||
InputSource inputStream = new InputSource(new StringReader(xml));
|
|
||||||
return docBuilder.parse(inputStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Document getDocument() throws ParserConfigurationException {
|
|
||||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
|
||||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
|
||||||
return docBuilder.newDocument();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
package gr.cite.annotation.common.enums;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonValue;
|
|
||||||
import gr.cite.annotation.data.conventers.DatabaseEnum;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public enum AnnotationProtectionType implements DatabaseEnum<Short> {
|
|
||||||
|
|
||||||
Private((short) 0),
|
|
||||||
EntityAccessors((short) 1);
|
|
||||||
|
|
||||||
private final Short value;
|
|
||||||
|
|
||||||
AnnotationProtectionType(Short value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonValue
|
|
||||||
public Short getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<Short, AnnotationProtectionType> map = EnumUtils.getEnumValueMap(AnnotationProtectionType.class);
|
|
||||||
|
|
||||||
public static AnnotationProtectionType of(Short i) {
|
|
||||||
return map.get(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package gr.cite.annotation.common.enums;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonValue;
|
|
||||||
import gr.cite.annotation.data.conventers.DatabaseEnum;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public enum ContactInfoType implements DatabaseEnum<Short> {
|
|
||||||
Email((short) 0),
|
|
||||||
MobilePhone((short) 1),
|
|
||||||
LandLinePhone((short) 2);
|
|
||||||
private final Short value;
|
|
||||||
|
|
||||||
ContactInfoType(Short value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@JsonValue
|
|
||||||
public Short getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<Short, ContactInfoType> map = EnumUtils.getEnumValueMap(ContactInfoType.class);
|
|
||||||
|
|
||||||
public static ContactInfoType of(Short i) {
|
|
||||||
return map.get(i);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package gr.cite.annotation.common.enums;
|
|
||||||
|
|
||||||
import gr.cite.annotation.data.conventers.DatabaseEnum;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class EnumUtils {
|
|
||||||
public static <EnumType extends Enum<EnumType> & DatabaseEnum<EnumValue>, EnumValue> Map<EnumValue, EnumType> getEnumValueMap(Class<EnumType> enumType){
|
|
||||||
HashMap<EnumValue, EnumType> map = new HashMap<>();
|
|
||||||
for (EnumType v : enumType.getEnumConstants()) {
|
|
||||||
map.put(v.getValue(), v);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
package gr.cite.annotation.common.enums;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonValue;
|
|
||||||
import gr.cite.annotation.data.conventers.DatabaseEnum;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public enum IsActive implements DatabaseEnum<Short> {
|
|
||||||
Inactive((short) 0),
|
|
||||||
Active((short) 1);
|
|
||||||
|
|
||||||
private final Short value;
|
|
||||||
|
|
||||||
IsActive(Short value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonValue
|
|
||||||
public Short getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<Short, IsActive> map = EnumUtils.getEnumValueMap(IsActive.class);
|
|
||||||
|
|
||||||
public static IsActive of(Short i) {
|
|
||||||
return map.get(i);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package gr.cite.annotation.common.enums;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonValue;
|
|
||||||
import gr.cite.annotation.data.conventers.DatabaseEnum;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public enum TenantConfigurationType implements DatabaseEnum<Short> {
|
|
||||||
EMAIL_CLIENT_CONFIGURATION((short)1),
|
|
||||||
DEFAULT_USER_LOCALE((short)3),
|
|
||||||
NOTIFIER_LIST((short)4);
|
|
||||||
|
|
||||||
private final Short value;
|
|
||||||
|
|
||||||
TenantConfigurationType(Short value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonValue
|
|
||||||
public Short getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<Short, TenantConfigurationType> map = EnumUtils.getEnumValueMap(TenantConfigurationType.class);
|
|
||||||
|
|
||||||
public static TenantConfigurationType of(Short i) {
|
|
||||||
return map.get(i);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
package gr.cite.annotation.common.lock;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class LockByKeyManager {
|
|
||||||
|
|
||||||
private static class LockWrapper {
|
|
||||||
private final ReentrantLock lock = new ReentrantLock();
|
|
||||||
private final AtomicInteger numberOfThreadsInQueue = new AtomicInteger(1);
|
|
||||||
|
|
||||||
private LockWrapper addThreadInQueue() {
|
|
||||||
numberOfThreadsInQueue.incrementAndGet();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int removeThreadFromQueue() {
|
|
||||||
return numberOfThreadsInQueue.decrementAndGet();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ConcurrentHashMap<String, LockWrapper> locks = new ConcurrentHashMap<String, LockWrapper>();
|
|
||||||
|
|
||||||
public void lock(String key) {
|
|
||||||
LockWrapper lockWrapper = locks.compute(key, (k, v) -> v == null ? new LockWrapper() : v.addThreadInQueue());
|
|
||||||
lockWrapper.lock.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean tryLock(String key, long timeout, TimeUnit unit) throws InterruptedException {
|
|
||||||
LockWrapper lockWrapper = null;
|
|
||||||
try {
|
|
||||||
lockWrapper = locks.compute(key, (k, v) -> v == null ? new LockWrapper() : v.addThreadInQueue());
|
|
||||||
return lockWrapper.lock.tryLock(timeout, unit);
|
|
||||||
} catch (Exception ex){
|
|
||||||
if (lockWrapper != null && lockWrapper.removeThreadFromQueue() == 0) {
|
|
||||||
// NB : We pass in the specific value to remove to handle the case where another thread would queue right before the removal
|
|
||||||
locks.remove(key, lockWrapper);
|
|
||||||
}
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unlock(String key) {
|
|
||||||
LockWrapper lockWrapper = locks.get(key);
|
|
||||||
lockWrapper.lock.unlock();
|
|
||||||
if (lockWrapper.removeThreadFromQueue() == 0) {
|
|
||||||
// NB : We pass in the specific value to remove to handle the case where another thread would queue right before the removal
|
|
||||||
locks.remove(key, lockWrapper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,125 +0,0 @@
|
||||||
package gr.cite.annotation.common.scope.fake;
|
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.web.context.request.RequestAttributes;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class FakeRequestAttributes implements RequestAttributes {
|
|
||||||
private Map<String, Object> requestAttributeMap = new HashMap<>();
|
|
||||||
private final Map<String, Runnable> requestDestructionCallbacks = new LinkedHashMap<>(8);
|
|
||||||
private volatile boolean requestActive = true;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getAttribute(String name, int scope) {
|
|
||||||
if (scope == RequestAttributes.SCOPE_REQUEST) {
|
|
||||||
if (!isRequestActive()) {
|
|
||||||
throw new IllegalStateException("Cannot ask for request attribute - request is not active anymore!");
|
|
||||||
}
|
|
||||||
return this.requestAttributeMap.get(name);
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Only " + RequestAttributes.SCOPE_REQUEST + " allowed for " + FakeRequestAttributes.class.getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAttribute(String name, Object value, int scope) {
|
|
||||||
if (scope == RequestAttributes.SCOPE_REQUEST) {
|
|
||||||
if (!isRequestActive()) {
|
|
||||||
throw new IllegalStateException("Cannot set request attribute - request is not active anymore!");
|
|
||||||
}
|
|
||||||
this.requestAttributeMap.put(name, value);
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Only " + RequestAttributes.SCOPE_REQUEST + " allowed for " + FakeRequestAttributes.class.getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeAttribute(String name, int scope) {
|
|
||||||
if (scope == RequestAttributes.SCOPE_REQUEST) {
|
|
||||||
if (isRequestActive()) {
|
|
||||||
removeRequestDestructionCallback(name);
|
|
||||||
this.requestAttributeMap.remove(name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Only " + RequestAttributes.SCOPE_REQUEST + " allowed for " + FakeRequestAttributes.class.getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getAttributeNames(int scope) {
|
|
||||||
if (scope == RequestAttributes.SCOPE_REQUEST) {
|
|
||||||
if (!isRequestActive()) {
|
|
||||||
throw new IllegalStateException("Cannot ask for request attributes - request is not active anymore!");
|
|
||||||
}
|
|
||||||
return this.requestAttributeMap.keySet().toArray(new String[0]);
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Only " + RequestAttributes.SCOPE_REQUEST + " allowed for " + FakeRequestAttributes.class.getSimpleName());
|
|
||||||
}
|
|
||||||
//return new String[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerDestructionCallback(String name, Runnable callback, int scope) {
|
|
||||||
if (scope == SCOPE_REQUEST) {
|
|
||||||
registerRequestDestructionCallback(name, callback);
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Only " + RequestAttributes.SCOPE_REQUEST + " allowed for " + FakeRequestAttributes.class.getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void registerRequestDestructionCallback(String name, Runnable callback) {
|
|
||||||
Assert.notNull(name, "Name must not be null");
|
|
||||||
Assert.notNull(callback, "Callback must not be null");
|
|
||||||
synchronized (this.requestDestructionCallbacks) {
|
|
||||||
this.requestDestructionCallbacks.put(name, callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object resolveReference(String key) {
|
|
||||||
// Not supported
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSessionId() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getSessionMutex() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void requestCompleted() {
|
|
||||||
executeRequestDestructionCallbacks();
|
|
||||||
for (String name : getAttributeNames(RequestAttributes.SCOPE_REQUEST)) {
|
|
||||||
this.removeAttribute(name, RequestAttributes.SCOPE_REQUEST);
|
|
||||||
}
|
|
||||||
this.requestActive = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final boolean isRequestActive() {
|
|
||||||
return this.requestActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private final void removeRequestDestructionCallback(String name) {
|
|
||||||
Assert.notNull(name, "Name must not be null");
|
|
||||||
synchronized (this.requestDestructionCallbacks) {
|
|
||||||
this.requestDestructionCallbacks.remove(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void executeRequestDestructionCallbacks() {
|
|
||||||
synchronized (this.requestDestructionCallbacks) {
|
|
||||||
for (Runnable runnable : this.requestDestructionCallbacks.values()) {
|
|
||||||
runnable.run();
|
|
||||||
}
|
|
||||||
this.requestDestructionCallbacks.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package gr.cite.annotation.common.scope.fake;
|
|
||||||
|
|
||||||
import org.springframework.web.context.request.RequestAttributes;
|
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
|
|
||||||
public class FakeRequestScope implements Closeable {
|
|
||||||
private RequestAttributes initialRequestAttributes = null;
|
|
||||||
private FakeRequestAttributes currentRequestAttributes = null;
|
|
||||||
boolean isInUse = false;
|
|
||||||
|
|
||||||
public FakeRequestScope() {
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
this.close();
|
|
||||||
this.isInUse = true;
|
|
||||||
|
|
||||||
this.initialRequestAttributes = RequestContextHolder.getRequestAttributes();
|
|
||||||
this.currentRequestAttributes = new FakeRequestAttributes();
|
|
||||||
RequestContextHolder.setRequestAttributes(this.currentRequestAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
if (!this.isInUse) return;
|
|
||||||
this.isInUse = false;
|
|
||||||
|
|
||||||
if (initialRequestAttributes != null) RequestContextHolder.setRequestAttributes(initialRequestAttributes);
|
|
||||||
else RequestContextHolder.resetRequestAttributes();
|
|
||||||
|
|
||||||
if (currentRequestAttributes != null) currentRequestAttributes.requestCompleted();
|
|
||||||
|
|
||||||
this.initialRequestAttributes = null;
|
|
||||||
this.currentRequestAttributes = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package gr.cite.annotation.common.scope.tenant;
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableConfigurationProperties(MultitenancyProperties.class)
|
|
||||||
public class MultitenancyConfiguration {
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package gr.cite.annotation.common.scope.tenant;
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
|
|
||||||
@ConfigurationProperties(prefix = "tenant.multitenancy")
|
|
||||||
public class MultitenancyProperties {
|
|
||||||
private boolean isMultitenant;
|
|
||||||
private String defaultTenantCode;
|
|
||||||
|
|
||||||
public boolean isMultitenant() {
|
|
||||||
return isMultitenant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIsMultitenant(boolean multitenant) {
|
|
||||||
isMultitenant = multitenant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMultitenant(boolean multitenant) {
|
|
||||||
isMultitenant = multitenant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDefaultTenantCode() {
|
|
||||||
return defaultTenantCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaultTenantCode(String defaultTenantCode) {
|
|
||||||
this.defaultTenantCode = defaultTenantCode;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
package gr.cite.annotation.common.scope.tenant;
|
|
||||||
|
|
||||||
import gr.cite.annotation.data.tenant.TenantScopedBaseEntity;
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.context.annotation.RequestScope;
|
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@RequestScope
|
|
||||||
public class TenantScope {
|
|
||||||
public static final String TenantReplaceParameter = "::TenantCode::";
|
|
||||||
private final MultitenancyProperties multitenancy;
|
|
||||||
private final AtomicReference<UUID> tenant = new AtomicReference<>();
|
|
||||||
private final AtomicReference<String> tenantCode = new AtomicReference<>();
|
|
||||||
private final AtomicReference<UUID> initialTenant = new AtomicReference<>();
|
|
||||||
private final AtomicReference<String> initialTenantCode = new AtomicReference<>();
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public TenantScope(MultitenancyProperties multitenancy) {
|
|
||||||
this.multitenancy = multitenancy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isMultitenant() {
|
|
||||||
return multitenancy.isMultitenant();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDefaultTenantCode() {
|
|
||||||
return multitenancy.getDefaultTenantCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isSet() {
|
|
||||||
if (!this.isMultitenant())
|
|
||||||
return Boolean.TRUE;
|
|
||||||
return this.tenant.get() != null || this.isDefaultTenant();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isDefaultTenant() {
|
|
||||||
if (!this.isMultitenant())
|
|
||||||
return Boolean.TRUE;
|
|
||||||
return this.multitenancy.getDefaultTenantCode().equalsIgnoreCase(this.tenantCode.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
public UUID getTenant() throws InvalidApplicationException {
|
|
||||||
if (!this.isMultitenant())
|
|
||||||
return null;
|
|
||||||
if (this.tenant.get() == null && !this.isDefaultTenant())
|
|
||||||
throw new InvalidApplicationException("tenant not set");
|
|
||||||
return this.isDefaultTenant() ? null : this.tenant.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTenantCode() throws InvalidApplicationException {
|
|
||||||
if (!this.isMultitenant())
|
|
||||||
return null;
|
|
||||||
if (this.tenantCode.get() == null)
|
|
||||||
throw new InvalidApplicationException("tenant not set");
|
|
||||||
return this.tenantCode.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTempTenant(EntityManager entityManager, UUID tenant, String tenantCode) {
|
|
||||||
this.tenant.set(tenant);
|
|
||||||
this.tenantCode.set(tenantCode);
|
|
||||||
|
|
||||||
if (this.tenant.get() != null && !this.isDefaultTenant()) {
|
|
||||||
if(!this.isDefaultTenant()) {
|
|
||||||
entityManager
|
|
||||||
.unwrap(Session.class)
|
|
||||||
.enableFilter(TenantScopedBaseEntity.TENANT_FILTER)
|
|
||||||
.setParameter(TenantScopedBaseEntity.TENANT_FILTER_TENANT_PARAM, this.tenant.get().toString());
|
|
||||||
} else {
|
|
||||||
entityManager
|
|
||||||
.unwrap(Session.class)
|
|
||||||
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeTempTenant(EntityManager entityManager) {
|
|
||||||
this.tenant.set(this.initialTenant.get());
|
|
||||||
this.tenantCode.set(this.initialTenantCode.get());
|
|
||||||
if (this.initialTenant.get() != null && !this.isDefaultTenant()) {
|
|
||||||
if(!this.isDefaultTenant()) {
|
|
||||||
entityManager
|
|
||||||
.unwrap(Session.class)
|
|
||||||
.enableFilter(TenantScopedBaseEntity.TENANT_FILTER)
|
|
||||||
.setParameter(TenantScopedBaseEntity.TENANT_FILTER_TENANT_PARAM, this.tenant.get().toString());
|
|
||||||
} else {
|
|
||||||
entityManager
|
|
||||||
.unwrap(Session.class)
|
|
||||||
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTenant(UUID tenant, String tenantCode) {
|
|
||||||
if (this.isMultitenant()) {
|
|
||||||
this.tenant.set(tenant);
|
|
||||||
this.initialTenant.set(tenant);
|
|
||||||
this.tenantCode.set(tenantCode);
|
|
||||||
this.initialTenantCode.set(tenantCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package gr.cite.annotation.common.scope.tenant;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public interface TenantScoped {
|
|
||||||
void setTenantId(UUID tenantId);
|
|
||||||
UUID getTenantId();
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package gr.cite.annotation.common.scope.user;
|
|
||||||
|
|
||||||
import gr.cite.tools.logging.LoggerService;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.context.annotation.RequestScope;
|
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@RequestScope
|
|
||||||
public class UserScope {
|
|
||||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserScope.class));
|
|
||||||
private UUID userId = null;
|
|
||||||
|
|
||||||
public Boolean isSet(){
|
|
||||||
return this.userId != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UUID getUserId() throws InvalidApplicationException {
|
|
||||||
if (this.userId == null) throw new InvalidApplicationException("user not set");
|
|
||||||
return this.userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UUID getUserIdSafe() {
|
|
||||||
return this.userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserId(UUID userId) {
|
|
||||||
this.userId = userId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
package gr.cite.annotation.common.types.tenant;
|
|
||||||
|
|
||||||
|
|
||||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
|
||||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
|
||||||
import jakarta.xml.bind.annotation.XmlElement;
|
|
||||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
|
||||||
|
|
||||||
@XmlRootElement(name = "config")
|
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
|
||||||
public class TenantConfigEntity {
|
|
||||||
|
|
||||||
@XmlElement(name = "deposit-configuration")
|
|
||||||
private TenantDepositConfigEntity deposit;
|
|
||||||
|
|
||||||
@XmlElement(name = "file-transformers-configuration")
|
|
||||||
private TenantFileTransformersConfigEntity fileTransformers;
|
|
||||||
|
|
||||||
public TenantDepositConfigEntity getDeposit() {
|
|
||||||
return deposit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeposit(TenantDepositConfigEntity deposit) {
|
|
||||||
this.deposit = deposit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TenantFileTransformersConfigEntity getFileTransformers() {
|
|
||||||
return fileTransformers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFileTransformers(TenantFileTransformersConfigEntity fileTransformers) {
|
|
||||||
this.fileTransformers = fileTransformers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
package gr.cite.annotation.common.types.tenant;
|
|
||||||
|
|
||||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
|
||||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
|
||||||
import jakarta.xml.bind.annotation.XmlElement;
|
|
||||||
import jakarta.xml.bind.annotation.XmlElementWrapper;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
|
||||||
public class TenantDepositConfigEntity {
|
|
||||||
|
|
||||||
@XmlElementWrapper(name = "sources")
|
|
||||||
@XmlElement(name = "source")
|
|
||||||
private List<TenantSourceEntity> sources;
|
|
||||||
|
|
||||||
|
|
||||||
public List<TenantSourceEntity> getSources() {
|
|
||||||
return sources;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSources(List<TenantSourceEntity> sources) {
|
|
||||||
this.sources = sources;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package gr.cite.annotation.common.types.tenant;
|
|
||||||
|
|
||||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
|
||||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
|
||||||
import jakarta.xml.bind.annotation.XmlElement;
|
|
||||||
import jakarta.xml.bind.annotation.XmlElementWrapper;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
|
||||||
public class TenantFileTransformersConfigEntity {
|
|
||||||
|
|
||||||
@XmlElementWrapper(name = "sources")
|
|
||||||
@XmlElement(name = "source")
|
|
||||||
private List<TenantSourceEntity> sources;
|
|
||||||
|
|
||||||
public List<TenantSourceEntity> getSources() {
|
|
||||||
return sources;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSources(List<TenantSourceEntity> sources) {
|
|
||||||
this.sources = sources;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,79 +0,0 @@
|
||||||
package gr.cite.annotation.common.types.tenant;
|
|
||||||
|
|
||||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
|
||||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
|
||||||
import jakarta.xml.bind.annotation.XmlElement;
|
|
||||||
import jakarta.xml.bind.annotation.XmlElementWrapper;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
|
||||||
public class TenantSourceEntity {
|
|
||||||
|
|
||||||
@XmlElement(name = "url")
|
|
||||||
private String url;
|
|
||||||
|
|
||||||
@XmlElementWrapper(name = "codes")
|
|
||||||
@XmlElement(name = "code")
|
|
||||||
private List<String> codes;
|
|
||||||
|
|
||||||
@XmlElement(name = "issuer-url")
|
|
||||||
private String issuerUrl;
|
|
||||||
|
|
||||||
@XmlElement(name = "client-id")
|
|
||||||
private String clientId;
|
|
||||||
|
|
||||||
@XmlElement(name = "client-secret")
|
|
||||||
private String clientSecret;
|
|
||||||
|
|
||||||
@XmlElement(name = "scope")
|
|
||||||
private String scope;
|
|
||||||
|
|
||||||
public String getUrl() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUrl(String url) {
|
|
||||||
this.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getCodes() {
|
|
||||||
return codes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCodes(List<String> codes) {
|
|
||||||
this.codes = codes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIssuerUrl() {
|
|
||||||
return issuerUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIssuerUrl(String issuerUrl) {
|
|
||||||
this.issuerUrl = issuerUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getClientId() {
|
|
||||||
return clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClientId(String clientId) {
|
|
||||||
this.clientId = clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getClientSecret() {
|
|
||||||
return clientSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClientSecret(String clientSecret) {
|
|
||||||
this.clientSecret = clientSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getScope() {
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScope(String scope) {
|
|
||||||
this.scope = scope;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package gr.cite.annotation.common.types.tenantconfiguration;
|
|
||||||
|
|
||||||
public class DefaultUserLocaleConfigurationDataContainer {
|
|
||||||
|
|
||||||
public static class Field {
|
|
||||||
public static final String LANGUAGE = "language";
|
|
||||||
public static final String TIME_ZONE = "timeZone";
|
|
||||||
public static final String CULTURE = "culture";
|
|
||||||
}
|
|
||||||
private String language;
|
|
||||||
private String timeZone;
|
|
||||||
private String culture;
|
|
||||||
|
|
||||||
public String getLanguage() {
|
|
||||||
return language;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLanguage(String language) {
|
|
||||||
this.language = language;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTimeZone() {
|
|
||||||
return timeZone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTimeZone(String timeZone) {
|
|
||||||
this.timeZone = timeZone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCulture() {
|
|
||||||
return culture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCulture(String culture) {
|
|
||||||
this.culture = culture;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
package gr.cite.annotation.common.types.tenantconfiguration;
|
|
||||||
|
|
||||||
public class EmailClientConfigurationDataContainer {
|
|
||||||
|
|
||||||
public static class Field {
|
|
||||||
public static final String REQUIRE_CREDENTIALS = "requireCredentials";
|
|
||||||
public static final String ENABLE_SSL = "enableSSL";
|
|
||||||
public static final String CERTIFICATE_PATH = "certificatePath";
|
|
||||||
public static final String HOST_SERVER = "hostServer";
|
|
||||||
public static final String HOST_PORT_NO = "hostPortNo";
|
|
||||||
public static final String EMAIL_ADDRESS = "emailAddress";
|
|
||||||
public static final String EMAIL_USER_NAME = "emailUserName";
|
|
||||||
public static final String EMAIL_PASSWORD = "emailPassword";
|
|
||||||
}
|
|
||||||
private Boolean requireCredentials;
|
|
||||||
private Boolean enableSSL;
|
|
||||||
private String certificatePath;
|
|
||||||
private String hostServer;
|
|
||||||
private Integer hostPortNo;
|
|
||||||
private String emailAddress;
|
|
||||||
private String emailUserName;
|
|
||||||
private String emailPassword;
|
|
||||||
|
|
||||||
public Boolean getRequireCredentials() {
|
|
||||||
return requireCredentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRequireCredentials(Boolean requireCredentials) {
|
|
||||||
this.requireCredentials = requireCredentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean getEnableSSL() {
|
|
||||||
return enableSSL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEnableSSL(Boolean enableSSL) {
|
|
||||||
this.enableSSL = enableSSL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCertificatePath() {
|
|
||||||
return certificatePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCertificatePath(String certificatePath) {
|
|
||||||
this.certificatePath = certificatePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHostServer() {
|
|
||||||
return hostServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHostServer(String hostServer) {
|
|
||||||
this.hostServer = hostServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getHostPortNo() {
|
|
||||||
return hostPortNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHostPortNo(Integer hostPortNo) {
|
|
||||||
this.hostPortNo = hostPortNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmailAddress() {
|
|
||||||
return emailAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmailAddress(String emailAddress) {
|
|
||||||
this.emailAddress = emailAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmailUserName() {
|
|
||||||
return emailUserName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmailUserName(String emailUserName) {
|
|
||||||
this.emailUserName = emailUserName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmailPassword() {
|
|
||||||
return emailPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmailPassword(String emailPassword) {
|
|
||||||
this.emailPassword = emailPassword;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
package gr.cite.annotation.common.types.user;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class AdditionalInfoEntity {
|
|
||||||
private String avatarUrl;
|
|
||||||
private String timezone;
|
|
||||||
private String culture;
|
|
||||||
private String language;
|
|
||||||
private String roleOrganization;
|
|
||||||
private UUID organizationId;
|
|
||||||
|
|
||||||
public String getAvatarUrl() {
|
|
||||||
return avatarUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAvatarUrl(String avatarUrl) {
|
|
||||||
this.avatarUrl = avatarUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTimezone() {
|
|
||||||
return timezone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTimezone(String timezone) {
|
|
||||||
this.timezone = timezone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCulture() {
|
|
||||||
return culture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCulture(String culture) {
|
|
||||||
this.culture = culture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLanguage() {
|
|
||||||
return language;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLanguage(String language) {
|
|
||||||
this.language = language;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UUID getOrganizationId() {
|
|
||||||
return organizationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOrganizationId(UUID organizationId) {
|
|
||||||
this.organizationId = organizationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRoleOrganization() {
|
|
||||||
return roleOrganization;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRoleOrganization(String roleOrganization) {
|
|
||||||
this.roleOrganization = roleOrganization;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
package gr.cite.annotation.common.types.xml;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
import org.w3c.dom.NodeList;
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.transform.OutputKeys;
|
|
||||||
import javax.xml.transform.Transformer;
|
|
||||||
import javax.xml.transform.TransformerException;
|
|
||||||
import javax.xml.transform.TransformerFactory;
|
|
||||||
import javax.xml.transform.dom.DOMSource;
|
|
||||||
import javax.xml.transform.stream.StreamResult;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
|
|
||||||
|
|
||||||
public class XmlBuilder {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(XmlBuilder.class);
|
|
||||||
|
|
||||||
public static Document getDocument() {
|
|
||||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
|
||||||
DocumentBuilder docBuilder;
|
|
||||||
try {
|
|
||||||
docBuilder = docFactory.newDocumentBuilder();
|
|
||||||
Document doc = docBuilder.newDocument();
|
|
||||||
return doc;
|
|
||||||
} catch (ParserConfigurationException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String generateXml(Document doc) {
|
|
||||||
TransformerFactory tFact = TransformerFactory.newInstance();
|
|
||||||
Transformer trans;
|
|
||||||
try {
|
|
||||||
trans = tFact.newTransformer();
|
|
||||||
StringWriter writer = new StringWriter();
|
|
||||||
StreamResult result = new StreamResult(writer);
|
|
||||||
DOMSource source = new DOMSource(doc);
|
|
||||||
trans.setOutputProperty(OutputKeys.INDENT, "yes");
|
|
||||||
trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
|
|
||||||
trans.transform(source, result);
|
|
||||||
return writer.toString();
|
|
||||||
} catch (TransformerException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Document fromXml(String xml) {
|
|
||||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
|
||||||
DocumentBuilder docBuilder;
|
|
||||||
try {
|
|
||||||
docBuilder = docFactory.newDocumentBuilder();
|
|
||||||
InputSource inputStream = new InputSource(new StringReader(xml));
|
|
||||||
Document doc = docBuilder.parse(inputStream);
|
|
||||||
return doc;
|
|
||||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static Element getNodeFromListByTagName(NodeList list, String tagName) {
|
|
||||||
for (int temp = 0; temp < list.getLength(); temp++) {
|
|
||||||
Node element = list.item(temp);
|
|
||||||
if (element.getNodeType() == Node.ELEMENT_NODE) {
|
|
||||||
if (element.getNodeName().equals(tagName)) return (Element) element;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package gr.cite.annotation.common.types.xml;
|
|
||||||
|
|
||||||
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
|
|
||||||
public interface XmlSerializable<T> {
|
|
||||||
Element toXml(Document doc);
|
|
||||||
|
|
||||||
T fromXml(Element item);
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
package gr.cite.annotation.common.validation;
|
|
||||||
|
|
||||||
import gr.cite.annotation.convention.ConventionService;
|
|
||||||
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
|
|
||||||
import gr.cite.tools.exception.MyValidationException;
|
|
||||||
import gr.cite.tools.validation.AbstractValidator;
|
|
||||||
import gr.cite.tools.validation.ValidationResult;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public abstract class BaseValidator<T> extends AbstractValidator<T> {
|
|
||||||
protected final ConventionService conventionService;
|
|
||||||
protected final ErrorThesaurusProperties errors;
|
|
||||||
|
|
||||||
protected BaseValidator(ConventionService conventionService, ErrorThesaurusProperties errors) {
|
|
||||||
this.conventionService = conventionService;
|
|
||||||
this.errors = errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void validateForce(Object target) {
|
|
||||||
this.validate(target);
|
|
||||||
ValidationResult result = result();
|
|
||||||
if (!result.isValid()) {
|
|
||||||
List<Map.Entry<String, List<String>>> errorsMap = this.flattenValidationResult();
|
|
||||||
throw new MyValidationException(this.errors.getModelValidation().getCode(), errorsMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Boolean isValidGuid(UUID guid) {
|
|
||||||
return this.conventionService.isValidGuid(guid);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Boolean isValidHash(String hash) {
|
|
||||||
return this.conventionService.isValidHash(hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Boolean isEmpty(String value) {
|
|
||||||
return this.conventionService.isNullOrEmpty(value);
|
|
||||||
}
|
|
||||||
protected Boolean isListNullOrEmpty(List<?> value) {
|
|
||||||
return this.conventionService.isListNullOrEmpty(value);
|
|
||||||
}
|
|
||||||
protected Boolean isNull(Object value) {
|
|
||||||
return value == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Boolean isNull(Collection<?> value) {
|
|
||||||
return value == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Boolean lessEqualLength(String value, int size) {
|
|
||||||
return value.length() <= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Boolean lessEqual(Integer value, int target) {
|
|
||||||
return value <= target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
package gr.cite.annotation.common.validation;
|
|
||||||
|
|
||||||
import gr.cite.annotation.convention.ConventionService;
|
|
||||||
import gr.cite.annotation.errorcode.ErrorThesaurusProperties;
|
|
||||||
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;
|
|
||||||
|
|
||||||
@Component(UuidValidator.ValidatorName)
|
|
||||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
|
||||||
public class UuidValidator extends BaseValidator<UUID> {
|
|
||||||
|
|
||||||
public static final String ValidatorName = "UuidValidator";
|
|
||||||
|
|
||||||
private final MessageSource messageSource;
|
|
||||||
|
|
||||||
protected UuidValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
|
|
||||||
super(conventionService, errors);
|
|
||||||
this.messageSource = messageSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<UUID> modelClass() {
|
|
||||||
return UUID.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<Specification> specifications(UUID item) {
|
|
||||||
return Arrays.asList(
|
|
||||||
this.spec()
|
|
||||||
.must(() -> this.isValidGuid(item))
|
|
||||||
.failOn("uuid").failWith(messageSource.getMessage("Validation_Required", new Object[]{"uuid"}, LocaleContextHolder.getLocale()))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue