Skip to content

Commit 271d8b5

Browse files
1536 - [MASTER DATA. REFERENCE DATA] MVP for look-ups (#1574)
Co-authored-by: vburlachenko <slaboezveno3@gmail.com>
1 parent 4572bba commit 271d8b5

File tree

137 files changed

+6501
-298
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+6501
-298
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ node_modules/
2323
/tests/dist/
2424
/playwright/.cache/
2525
.tool-versions
26+
.vscode

docker/demo.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ services:
1717
- SPRING_DATASOURCE_URL=jdbc:postgresql://database:5432/${POSTGRES_DATABASE}
1818
- SPRING_DATASOURCE_USERNAME=${POSTGRES_USER}
1919
- SPRING_DATASOURCE_PASSWORD=${POSTGRES_PASSWORD}
20+
- SPRING_CUSTOM-DATASOURCE_URL=jdbc:postgresql://database:5432/${POSTGRES_DATABASE}?schema=lookup_tables_schema
21+
- SPRING_CUSTOM-DATASOURCE_USERNAME=${POSTGRES_USER}
22+
- SPRING_CUSTOM-DATASOURCE_PASSWORD=${POSTGRES_PASSWORD}
2023
depends_on:
2124
- database
2225
ports:

gradle/libs.versions.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ spring-webflux = '6.0.9'
33
reactor-extra = '3.5.1'
44
micrometer-registry-prometheus = '1.9.0'
55
ingestion-contract-server = '0.1.32'
6-
oddrn-generator-java = '0.1.20'
6+
oddrn-generator-java = '0.1.21'
77
odd-integration-manifests = '0.0.6'
88
apache-collections = '4.4'
99
apache-lang = '3.12.0'
@@ -33,7 +33,7 @@ shedlock-version = '4.42.0'
3333
json-schema-validator = '1.0.84'
3434
caffeine = '3.1.1'
3535
lombok = '1.18.24'
36-
testcontainers = '1.18.3'
36+
testcontainers = '1.19.3'
3737
slf4j-api = '1.7.30'
3838
logback = '1.2.11'
3939
easy-random-core = '5.0.0'
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.opendatadiscovery.oddplatform.annotation;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
import org.springframework.transaction.annotation.Transactional;
8+
9+
@Target({ElementType.METHOD, ElementType.TYPE})
10+
@Retention(RetentionPolicy.RUNTIME)
11+
@Transactional("customTransactionManager")
12+
public @interface ReactiveCustomTransactional {
13+
}

odd-platform-api/src/main/java/org/opendatadiscovery/oddplatform/auth/manager/AuthorizationManagerType.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ public enum AuthorizationManagerType {
66
DATASET_FIELD,
77
TERM,
88
QUERY_EXAMPLE,
9+
LOOKUP_TABLE,
10+
LOOKUP_TABLE_DEFINITION,
11+
LOOKUP_TABLE_DATA,
912
ALERT,
1013
DEG
1114
}

odd-platform-api/src/main/java/org/opendatadiscovery/oddplatform/auth/manager/ReactiveAuthorizationManagerFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public final class ReactiveAuthorizationManagerFactory {
1313
private static final String DATASET_FIELD_ID = "dataset_field_id";
1414
private static final String DATA_ENTITY_GROUP_ID = "data_entity_group_id";
1515
private static final String QUERY_EXAMPLE_ID = "example_id";
16+
private static final String LOOKUP_TABLE_ID = "lookup_table_id";
17+
private static final String LOOKUP_TABLE_DEFINITION_ID = "column_id";
18+
private static final String LOOKUP_TABLE_DATA_ID = "row_id";
1619
private static final String ALERT_ID = "alert_id";
1720

1821
private ReactiveAuthorizationManagerFactory() {
@@ -46,6 +49,9 @@ private static String resourceExtractorVariableName(final AuthorizationManagerTy
4649
case ALERT -> ALERT_ID;
4750
case DEG -> DATA_ENTITY_GROUP_ID;
4851
case QUERY_EXAMPLE -> QUERY_EXAMPLE_ID;
52+
case LOOKUP_TABLE -> LOOKUP_TABLE_ID;
53+
case LOOKUP_TABLE_DEFINITION -> LOOKUP_TABLE_DEFINITION_ID;
54+
case LOOKUP_TABLE_DATA -> LOOKUP_TABLE_DATA_ID;
4955
default -> throw new IllegalArgumentException("Unsupported resource type: " + type);
5056
};
5157
}

odd-platform-api/src/main/java/org/opendatadiscovery/oddplatform/auth/util/SecurityConstants.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@
4343
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.DATA_SOURCE_DELETE;
4444
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.DATA_SOURCE_TOKEN_REGENERATE;
4545
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.DATA_SOURCE_UPDATE;
46+
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.LOOKUP_TABLE_CREATE;
47+
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.LOOKUP_TABLE_DATA_CREATE;
48+
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.LOOKUP_TABLE_DATA_DELETE;
49+
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.LOOKUP_TABLE_DATA_UPDATE;
50+
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.LOOKUP_TABLE_DEFINITION_CREATE;
51+
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.LOOKUP_TABLE_DEFINITION_DELETE;
52+
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.LOOKUP_TABLE_DEFINITION_UPDATE;
53+
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.LOOKUP_TABLE_DELETE;
54+
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.LOOKUP_TABLE_UPDATE;
4655
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.NAMESPACE_CREATE;
4756
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.NAMESPACE_DELETE;
4857
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.NAMESPACE_UPDATE;
@@ -73,6 +82,7 @@
7382
import static org.opendatadiscovery.oddplatform.dto.policy.PolicyPermissionDto.TERM_UPDATE;
7483
import static org.springframework.http.HttpMethod.DELETE;
7584
import static org.springframework.http.HttpMethod.GET;
85+
import static org.springframework.http.HttpMethod.PATCH;
7686
import static org.springframework.http.HttpMethod.POST;
7787
import static org.springframework.http.HttpMethod.PUT;
7888

@@ -97,6 +107,8 @@ public final class SecurityConstants {
97107
new SecurityRule(NO_CONTEXT, new PathPatternParserServerWebExchangeMatcher("/api/terms", POST), TERM_CREATE),
98108
new SecurityRule(NO_CONTEXT, new PathPatternParserServerWebExchangeMatcher("/api/queryexample", POST),
99109
QUERY_EXAMPLE_CREATE),
110+
new SecurityRule(NO_CONTEXT, new PathPatternParserServerWebExchangeMatcher("/api/referencedata/table", POST),
111+
LOOKUP_TABLE_CREATE),
100112
new SecurityRule(NO_CONTEXT, new PathPatternParserServerWebExchangeMatcher("/api/datasources", POST),
101113
DATA_SOURCE_CREATE),
102114
new SecurityRule(NO_CONTEXT,
@@ -290,6 +302,36 @@ DATA_ENTITY, new PathPatternParserServerWebExchangeMatcher(
290302
new SecurityRule(NO_CONTEXT,
291303
new PathPatternParserServerWebExchangeMatcher(
292304
"/api/queryexample/{example_id}/dataset/{data_entity_id}", DELETE),
293-
QUERY_EXAMPLE_DATASET_DELETE)
305+
QUERY_EXAMPLE_DATASET_DELETE),
306+
new SecurityRule(NO_CONTEXT,
307+
new PathPatternParserServerWebExchangeMatcher("/api/referencedata/table/{lookup_table_id}", PUT),
308+
LOOKUP_TABLE_UPDATE),
309+
new SecurityRule(NO_CONTEXT,
310+
new PathPatternParserServerWebExchangeMatcher("/api/referencedata/table/{lookup_table_id}", DELETE),
311+
LOOKUP_TABLE_DELETE),
312+
new SecurityRule(NO_CONTEXT,
313+
new PathPatternParserServerWebExchangeMatcher(
314+
"/api/referencedata/table/{lookup_table_id}/columns", POST),
315+
LOOKUP_TABLE_DEFINITION_CREATE),
316+
new SecurityRule(NO_CONTEXT,
317+
new PathPatternParserServerWebExchangeMatcher(
318+
"/api/referencedata/table/{lookup_table_id}/column/{column_id}", PATCH),
319+
LOOKUP_TABLE_DEFINITION_UPDATE),
320+
new SecurityRule(NO_CONTEXT,
321+
new PathPatternParserServerWebExchangeMatcher(
322+
"/api/referencedata/table/{lookup_table_id}/column/{column_id}", DELETE),
323+
LOOKUP_TABLE_DEFINITION_DELETE),
324+
new SecurityRule(NO_CONTEXT,
325+
new PathPatternParserServerWebExchangeMatcher(
326+
"/api/referencedata/table/{lookup_table_id}/data", POST),
327+
LOOKUP_TABLE_DATA_CREATE),
328+
new SecurityRule(NO_CONTEXT,
329+
new PathPatternParserServerWebExchangeMatcher(
330+
"/api/referencedata/table/{lookup_table_id}/data/{row_id}", PUT),
331+
LOOKUP_TABLE_DATA_UPDATE),
332+
new SecurityRule(NO_CONTEXT,
333+
new PathPatternParserServerWebExchangeMatcher(
334+
"/api/referencedata/table/{lookup_table_id}/data/{row_id}", DELETE),
335+
LOOKUP_TABLE_DATA_DELETE)
294336
);
295337
}

odd-platform-api/src/main/java/org/opendatadiscovery/oddplatform/config/R2DBCConfiguration.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,23 @@
55
import io.r2dbc.spi.ConnectionFactories;
66
import io.r2dbc.spi.ConnectionFactory;
77
import io.r2dbc.spi.ConnectionFactoryOptions;
8+
import org.springframework.beans.factory.annotation.Qualifier;
9+
import org.springframework.beans.factory.annotation.Value;
810
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
911
import org.springframework.boot.autoconfigure.r2dbc.R2dbcProperties;
1012
import org.springframework.boot.context.properties.PropertyMapper;
1113
import org.springframework.context.annotation.Bean;
1214
import org.springframework.context.annotation.Configuration;
15+
import org.springframework.context.annotation.Primary;
1316
import org.springframework.r2dbc.connection.R2dbcTransactionManager;
17+
import org.springframework.r2dbc.core.DatabaseClient;
1418
import org.springframework.transaction.ReactiveTransactionManager;
1519

1620
@Configuration
1721
public class R2DBCConfiguration {
1822

1923
@Bean(destroyMethod = "dispose")
24+
@Primary
2025
public ConnectionPool connectionFactory(final DataSourceProperties dataSourceProperties,
2126
final R2dbcProperties properties) {
2227
final String r2dbcUrl = dataSourceProperties.getUrl().replace("jdbc", "r2dbc");
@@ -42,8 +47,59 @@ public ConnectionPool connectionFactory(final DataSourceProperties dataSourcePro
4247
return new ConnectionPool(builder.build());
4348
}
4449

50+
@Bean(destroyMethod = "dispose")
51+
@Qualifier("customConnectionPool")
52+
public ConnectionPool databaseClientForCustomSchema(
53+
@Value("${spring.custom-datasource.url}") final String url,
54+
@Value("${spring.custom-datasource.username}") final String username,
55+
@Value("${spring.custom-datasource.password}") final String password,
56+
final R2dbcProperties properties) {
57+
final String r2dbcUrl = url.replace("jdbc", "r2dbc");
58+
final ConnectionFactory factory = ConnectionFactories.get(ConnectionFactoryOptions.parse(r2dbcUrl).mutate()
59+
.option(ConnectionFactoryOptions.PROTOCOL, "postgresql")
60+
.option(ConnectionFactoryOptions.USER, username)
61+
.option(ConnectionFactoryOptions.PASSWORD, password)
62+
.build());
63+
64+
final R2dbcProperties.Pool pool = properties.getPool();
65+
final PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
66+
final ConnectionPoolConfiguration.Builder builder = ConnectionPoolConfiguration.builder(factory);
67+
map.from(pool.getMaxIdleTime()).to(builder::maxIdleTime);
68+
map.from(pool.getMaxLifeTime()).to(builder::maxLifeTime);
69+
map.from(pool.getMaxAcquireTime()).to(builder::maxAcquireTime);
70+
map.from(pool.getMaxCreateConnectionTime()).to(builder::maxCreateConnectionTime);
71+
map.from(pool.getInitialSize()).to(builder::initialSize);
72+
map.from(pool.getMaxSize()).to(builder::maxSize);
73+
map.from(pool.getValidationQuery()).whenHasText().to(builder::validationQuery);
74+
map.from(pool.getValidationDepth()).to(builder::validationDepth);
75+
map.from(pool.getMinIdle()).to(builder::minIdle);
76+
map.from(pool.getMaxValidationTime()).to(builder::maxValidationTime);
77+
78+
return new ConnectionPool(builder.build());
79+
}
80+
81+
@Bean
82+
public DatabaseClient databaseClient(final ConnectionFactory schema1ConnectionFactory) {
83+
return DatabaseClient.create(schema1ConnectionFactory);
84+
}
85+
86+
@Bean
87+
@Qualifier("customDataClient")
88+
public DatabaseClient databaseClientCustomTables(
89+
@Qualifier("customConnectionPool") final ConnectionFactory connectionFactory) {
90+
return DatabaseClient.create(connectionFactory);
91+
}
92+
4593
@Bean
94+
@Primary
4695
public ReactiveTransactionManager reactiveTransactionManager(final ConnectionFactory connectionFactory) {
4796
return new R2dbcTransactionManager(connectionFactory);
4897
}
98+
99+
@Bean
100+
@Qualifier("customTransactionManager")
101+
public ReactiveTransactionManager reactiveCustomTransactionManager(
102+
@Qualifier("customConnectionPool") final ConnectionFactory connectionFactory) {
103+
return new R2dbcTransactionManager(connectionFactory);
104+
}
49105
}

0 commit comments

Comments
 (0)