From 829cc9e874211fccb8adc3449a4962032d031ecb Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Tue, 25 Feb 2025 10:56:38 +0100 Subject: [PATCH 01/11] Fixed some tests Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- .gitlab-ci.yml | 7 -- .../at/tuwien/endpoints/SubsetEndpoint.java | 7 +- .../at/tuwien/endpoints/ViewEndpoint.java | 6 +- .../endpoint/SubsetEndpointUnitTest.java | 3 +- .../tuwien/endpoint/ViewEndpointUnitTest.java | 10 ++- .../DatabaseServiceIntegrationTest.java | 10 +-- .../java/at/tuwien/mapper/MariaDbMapper.java | 86 ++++++++++++++++++- .../at/tuwien/service/DatabaseService.java | 6 +- .../impl/DatabaseServiceMariaDbImpl.java | 12 +-- .../at/tuwien/api/database/CreateViewDto.java | 4 +- .../tuwien/api/database/query/FilterDto.java | 39 +++++++++ .../tuwien/api/database/query/SubsetDto.java | 33 +++++++ .../at/tuwien/endpoints/ViewEndpoint.java | 2 +- .../endpoints/ViewEndpointUnitTest.java | 8 +- .../tuwien/service/TableServiceUnitTest.java | 70 ++++++++++++++- .../tuwien/service/ViewServiceUnitTest.java | 5 +- .../java/at/tuwien/service/ViewService.java | 2 +- .../tuwien/service/impl/TableServiceImpl.java | 32 ++++--- .../tuwien/service/impl/ViewServiceImpl.java | 10 +-- .../main/java/at/tuwien/test/BaseTest.java | 10 ++- lib/python/dbrepo/api/dto.py | 1 + lib/python/tests/test_unit_container.py | 14 ++- lib/python/tests/test_unit_image.py | 5 +- lib/python/tests/test_unit_messages.py | 2 +- 24 files changed, 308 insertions(+), 76 deletions(-) create mode 100644 dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java create mode 100644 dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SubsetDto.java diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3928026c5a..c62365a4ed 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -285,13 +285,6 @@ test-data-service: junit: ./dbrepo-data-service/rest-service/target/surefire-reports/TEST-*.xml coverage: '/Total.*?([0-9]{1,3})%/' -test-upload-service: - image: maven:3-openjdk-${JAVA_VERSION} - stage: test - script: - - "mvn -f ./dbrepo-metadata-service/pom.xml clean install $MAVEN_OPTS -DskipTests" - - "mvn -f ./dbrepo-upload-service/pom.xml clean test $MAVEN_OPTS" - test-analyse-service: image: docker.io/python:${PYTHON_VERSION}-alpine${ALPINE_VERSION} stage: test diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java index 245774726f..6f6c26d99e 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java @@ -384,12 +384,7 @@ public class SubsetEndpoint extends RestEndpoint { final Dataset<Row> dataset = subsetService.getData(database, query); metricsService.countSubsetGetData(databaseId, subsetId); final String viewName = metadataMapper.queryDtoToViewName(subset); - databaseService.createView(database, CreateViewDto.builder() - .name(viewName) - .isPublic(false) - .isSchemaPublic(false) - .query(query) - .build()); + databaseService.createView(database, viewName, subset.getQuery()); final ViewDto view = databaseService.inspectView(database, viewName); headers.set("Access-Control-Expose-Headers", "X-Id X-Headers"); headers.set("X-Headers", String.join(",", view.getColumns().stream().map(ViewColumnDto::getInternalName).toList())); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 47b4bb81db..fdf4f62f55 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -152,12 +152,14 @@ public class ViewEndpoint extends RestEndpoint { }) public ResponseEntity<ViewDto> create(@NotNull @PathVariable("databaseId") UUID databaseId, @Valid @RequestBody CreateViewDto data) throws DatabaseUnavailableException, - DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, MetadataServiceException { + DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, MetadataServiceException, + TableNotFoundException, ImageNotFoundException { log.debug("endpoint create view, databaseId={}, data.name={}", databaseId, data.getName()); final DatabaseDto database = credentialService.getDatabase(databaseId); try { return ResponseEntity.status(HttpStatus.CREATED) - .body(databaseService.createView(database, data)); + .body(databaseService.createView(database, mariaDbMapper.nameToInternalName(data.getName()), + mariaDbMapper.subsetDtoToRawQuery(database, data.getQuery()))); } catch (SQLException e) { log.error("Failed to establish connection to database: {}", e.getMessage()); throw new DatabaseUnavailableException("Failed to establish connection to database: " + e.getMessage(), e); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java index f292264060..91ca4a1976 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java @@ -37,6 +37,7 @@ import java.util.Map; import java.util.UUID; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.*; @Log4j2 @@ -359,7 +360,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { .thenReturn(QUERY_5_DTO); when(subsetService.getData(any(DatabaseDto.class), anyString())) .thenReturn(mock); - when(databaseService.createView(any(DatabaseDto.class), any(CreateViewDto.class))) + when(databaseService.createView(any(DatabaseDto.class), anyString(), anyString())) .thenReturn(QUERY_5_VIEW_DTO); when(databaseService.inspectView(any(DatabaseDto.class), anyString())) .thenReturn(QUERY_5_VIEW_DTO); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java index 3421ed6124..82a9168e9f 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.*; @Log4j2 @@ -68,12 +69,13 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, - SQLException, DatabaseUnavailableException, MetadataServiceException { + SQLException, DatabaseUnavailableException, MetadataServiceException, TableNotFoundException, + ImageNotFoundException { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - when(databaseService.createView(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO)) + when(databaseService.createView(any(DatabaseDto.class), anyString(), anyString())) .thenReturn(VIEW_1_PRIVILEGED_DTO); /* test */ @@ -91,7 +93,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1_PRIVILEGED_DTO); doThrow(SQLException.class) .when(databaseService) - .createView(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO); + .createView(any(DatabaseDto.class), anyString(), anyString()); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -107,7 +109,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - when(databaseService.createView(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO)) + when(databaseService.createView(DATABASE_1_PRIVILEGED_DTO, VIEW_1_NAME, VIEW_1_QUERY)) .thenReturn(VIEW_1_PRIVILEGED_DTO); /* test */ diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java index 8fd4a26c5e..183752cb5c 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java @@ -4,9 +4,7 @@ import at.tuwien.api.database.ViewColumnDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.columns.ColumnDto; -import at.tuwien.api.database.table.columns.ColumnTypeDto; -import at.tuwien.api.database.table.columns.CreateTableColumnDto; +import at.tuwien.api.database.table.columns.*; import at.tuwien.api.database.table.constraints.ConstraintsDto; import at.tuwien.api.database.table.constraints.CreateTableConstraintsDto; import at.tuwien.api.database.table.constraints.foreign.CreateForeignKeyDto; @@ -75,7 +73,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { public void createView_succeeds() throws SQLException, ViewMalformedException { /* test */ - databaseService.createView(DATABASE_1_PRIVILEGED_DTO, VIEW_1_CREATE_DTO); + databaseService.createView(DATABASE_1_PRIVILEGED_DTO, VIEW_1_NAME, VIEW_1_QUERY); } @Test @@ -206,10 +204,10 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { assertColumn(columns.get(0), null, null, DATABASE_2_ID, "id", "id", ColumnTypeDto.BIGINT, 19L, 0L, false, null); assertColumn(columns.get(1), null, null, DATABASE_2_ID, "mode", "mode", ColumnTypeDto.ENUM, 3L, null, false, null); assertEquals(2, columns.get(1).getEnums().size()); - assertEquals(List.of("ABC", "DEF"), columns.get(1).getEnums()); + assertEquals(List.of("ABC", "DEF"), columns.get(1).getEnums().stream().map(EnumDto::getValue).toList()); assertColumn(columns.get(2), null, null, DATABASE_2_ID, "seq", "seq", ColumnTypeDto.SET, 5L, null, true, null); assertEquals(3, columns.get(2).getSets().size()); - assertEquals(List.of("1", "2", "3"), columns.get(2).getSets()); + assertEquals(List.of("1", "2", "3"), columns.get(2).getSets().stream().map(SetDto::getValue).toList()); /* ignore rest (constraints) */ } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java index 4e48c02786..226d8fb3c9 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java @@ -1,14 +1,17 @@ package at.tuwien.mapper; -import at.tuwien.api.database.table.TableDto; -import at.tuwien.api.database.table.TupleDeleteDto; -import at.tuwien.api.database.table.TupleDto; -import at.tuwien.api.database.table.TupleUpdateDto; +import at.tuwien.api.container.image.OperatorDto; +import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.query.FilterDto; +import at.tuwien.api.database.query.SubsetDto; +import at.tuwien.api.database.table.*; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.columns.CreateTableColumnDto; +import at.tuwien.exception.ImageNotFoundException; import at.tuwien.exception.QueryMalformedException; import at.tuwien.exception.TableMalformedException; +import at.tuwien.exception.TableNotFoundException; import at.tuwien.utils.MariaDbUtil; import org.mapstruct.Mapper; import org.mapstruct.Named; @@ -788,4 +791,79 @@ public interface MariaDbMapper { return statement.toString(); } + default String subsetDtoToRawQuery(DatabaseDto database, SubsetDto data) throws TableNotFoundException, ImageNotFoundException { + final StringBuilder builder = new StringBuilder("SELECT "); + final Optional<TableDto> optional = database.getTables() + .stream() + .filter(t -> t.getId().equals(data.getTableId())) + .findFirst(); + if (optional.isEmpty()) { + log.error("Failed to find table with id: {}", data.getTableId()); + throw new TableNotFoundException("Failed to find table"); + } + final List<ColumnDto> columns = optional.get() + .getColumns() + .stream() + .filter(c -> data.getColumns().contains(c.getId())) + .toList(); + if (data.getColumns().size() != columns.size()) { + log.error("Failed to find all requested columns"); + throw new TableNotFoundException("Failed to find all requested columns"); + } + builder.append(String.join(", ", columns.stream().map(column -> "`" + column.getInternalName() + "`").toList())); + builder.append("FROM `") + .append(optional.get().getInternalName()) + .append("`"); + if (data.getFilter() != null) { + builder.append(" WHERE "); + for (FilterDto filter : data.getFilter()) { + final Optional<ColumnDto> optional1 = optional.get() + .getColumns() + .stream() + .filter(c -> c.getId().equals(filter.getColumnId())) + .findFirst(); + if (optional1.isEmpty()) { + log.error("Failed to find filtered column with id: {}", filter.getColumnId()); + throw new TableNotFoundException("Failed to find filtered column"); + } + final ColumnDto column = optional1.get(); + final Optional<OperatorDto> optional2 = database.getContainer() + .getImage() + .getOperators() + .stream() + .filter(op -> op.getId().equals(filter.getOperatorId())) + .findFirst(); + if (optional2.isEmpty()) { + log.error("Failed to find operator with id: {}", filter.getOperatorId()); + throw new ImageNotFoundException("Failed to find operator"); + } + builder.append("`") + .append(column.getInternalName()) + .append("` ") + .append(optional2.get() + .getValue()) + .append(" ") + .append(tableColumnTypeQuote(column.getColumnType(), filter.getValue())); + if (filter.getIsAnd() != null) { + if (filter.getIsAnd()) { + builder.append(" AND "); + } else { + builder.append(" OR "); + } + } + } + } + log.trace("mapped raw query: {}", builder); + return builder.toString(); + } + + default String tableColumnTypeQuote(ColumnTypeDto data, String value) { + if (List.of(ColumnTypeDto.CHAR, ColumnTypeDto.VARCHAR, ColumnTypeDto.TINYTEXT, ColumnTypeDto.TEXT, + ColumnTypeDto.MEDIUMTEXT, ColumnTypeDto.LONGTEXT, ColumnTypeDto.DATE, ColumnTypeDto.DATETIME, + ColumnTypeDto.TIMESTAMP).contains(data)) { + return "'" + value + "'"; + } + return value; + } + } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java index c325d7b33a..8f07b6bfb2 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/DatabaseService.java @@ -1,6 +1,5 @@ package at.tuwien.service; -import at.tuwien.api.database.CreateViewDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.table.TableDto; @@ -40,12 +39,13 @@ public interface DatabaseService { /** * Creates a view in given data database with view definition. * @param database The data database object. - * @param data The view definition. + * @param viewName The view name. + * @param query The view query. * @return The generated view. * @throws SQLException * @throws ViewMalformedException */ - ViewDto createView(DatabaseDto database, CreateViewDto data) throws SQLException, + ViewDto createView(DatabaseDto database, String viewName, String query) throws SQLException, ViewMalformedException; /** diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java index f7e12c69f6..136a8d740c 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java @@ -118,16 +118,16 @@ public class DatabaseServiceMariaDbImpl extends DataConnector implements Databas } @Override - public ViewDto createView(DatabaseDto database, CreateViewDto data) throws SQLException, + public ViewDto createView(DatabaseDto database, String viewName, String query) throws SQLException, ViewMalformedException { final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); ViewDto view = ViewDto.builder() - .name(data.getName()) - .internalName(mariaDbMapper.nameToInternalName(data.getName())) - .query(data.getQuery()) + .name(viewName) + .internalName(mariaDbMapper.nameToInternalName(viewName)) + .query(query) .queryHash(Hashing.sha256() - .hashString(data.getQuery(), StandardCharsets.UTF_8) + .hashString(query, StandardCharsets.UTF_8) .toString()) .isPublic(database.getIsPublic()) .owner(database.getOwner()) @@ -139,7 +139,7 @@ public class DatabaseServiceMariaDbImpl extends DataConnector implements Databas try { /* create view if not exists */ final long start = System.currentTimeMillis(); - connection.prepareStatement(mariaDbMapper.viewCreateRawQuery(view.getInternalName(), data.getQuery())) + connection.prepareStatement(mariaDbMapper.viewCreateRawQuery(view.getInternalName(), query)) .execute(); log.trace("executed statement in {} ms", System.currentTimeMillis() - start); /* select view columns */ diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateViewDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateViewDto.java index 366845d083..f2c188c7e5 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateViewDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateViewDto.java @@ -1,5 +1,6 @@ package at.tuwien.api.database; +import at.tuwien.api.database.query.SubsetDto; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -24,8 +25,7 @@ public class CreateViewDto { private String name; @NotBlank - @Schema(example = "SELECT `id` FROM `air_quality`") - private String query; + private SubsetDto query; @NotNull @JsonProperty("is_public") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java new file mode 100644 index 0000000000..bcb4a338a2 --- /dev/null +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java @@ -0,0 +1,39 @@ +package at.tuwien.api.database.query; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +import java.util.UUID; + +@Getter +@Setter +@Builder +@EqualsAndHashCode +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class FilterDto { + + @NotNull + @JsonProperty("column_id") + @Schema(example = "14128033-54b5-4818-a489-21b0dded86e2") + private UUID columnId; + + @NotNull + @JsonProperty("operator_id") + @Schema(example = ">") + private UUID operatorId; + + @NotNull + @Schema(example = "1") + private String value; + + @JsonProperty("is_and") + @Schema(example = "false") + private Boolean isAnd; + +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SubsetDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SubsetDto.java new file mode 100644 index 0000000000..6255272482 --- /dev/null +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SubsetDto.java @@ -0,0 +1,33 @@ +package at.tuwien.api.database.query; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import lombok.extern.jackson.Jacksonized; + +import java.util.List; +import java.util.UUID; + +@Getter +@Setter +@Builder +@EqualsAndHashCode +@NoArgsConstructor +@AllArgsConstructor +@Jacksonized +@ToString +public class SubsetDto { + + @NotNull + @JsonProperty("table_id") + @Schema(example = "f7df2a7d-4ade-4c78-97b0-7c744d0893c7") + private UUID tableId; + + @NotNull + @Schema(example = "[\"e891ba86-0258-41a6-a8d9-ff58bc10b618\"]") + private List<UUID> columns; + + private List<FilterDto> filter; + +} diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 2214343ee6..1f4525cd8b 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -141,7 +141,7 @@ public class ViewEndpoint extends AbstractEndpoint { @NotNull @Valid @RequestBody CreateViewDto data, @NotNull Principal principal) throws NotAllowedException, MalformedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, - UserNotFoundException, SearchServiceException, SearchServiceConnectionException { + UserNotFoundException, SearchServiceException, SearchServiceConnectionException, TableNotFoundException, ImageNotFoundException { log.debug("endpoint create view, databaseId={}, data={}", databaseId, data); final Database database = databaseService.findById(databaseId); if (!database.getOwner().getId().equals(getId(principal))) { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java index 1fa3d59920..94e5a3bf0a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java @@ -141,7 +141,8 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"create-database-view"}) public void create_succeeds() throws UserNotFoundException, SearchServiceException, MalformedException, NotAllowedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, - SearchServiceConnectionException, DataServiceConnectionException { + SearchServiceConnectionException, DataServiceConnectionException, TableNotFoundException, + ImageNotFoundException { /* test */ create_generic(DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL, USER_1_ID, USER_1, DATABASE_1_USER_1_WRITE_ALL_ACCESS); @@ -481,10 +482,11 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { protected void create_generic(UUID databaseId, Database database, Principal principal, UUID userId, User user, DatabaseAccess access) throws MalformedException, DataServiceException, DataServiceConnectionException, NotAllowedException, UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { + AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, TableNotFoundException, + ImageNotFoundException { final CreateViewDto request = CreateViewDto.builder() .name(VIEW_1_NAME) - .query(VIEW_1_QUERY) + .query(VIEW_1_SUBSET_DTO) .isPublic(VIEW_1_PUBLIC) .build(); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java index 8cb5081f6d..9b0b7fcb1a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java @@ -2,14 +2,17 @@ package at.tuwien.service; import at.tuwien.api.database.table.CreateTableDto; import at.tuwien.api.database.table.TableStatisticDto; -import at.tuwien.api.database.table.columns.CreateTableColumnDto; +import at.tuwien.api.database.table.TableUpdateDto; import at.tuwien.api.database.table.columns.ColumnStatisticDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; +import at.tuwien.api.database.table.columns.CreateTableColumnDto; import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; import at.tuwien.api.database.table.constraints.CreateTableConstraintsDto; import at.tuwien.api.database.table.constraints.foreign.CreateForeignKeyDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.table.Table; +import at.tuwien.entities.database.table.columns.ColumnEnum; +import at.tuwien.entities.database.table.columns.ColumnSet; import at.tuwien.entities.database.table.columns.TableColumn; import at.tuwien.entities.database.table.columns.TableColumnType; import at.tuwien.entities.database.table.constraints.Constraints; @@ -340,6 +343,54 @@ public class TableServiceUnitTest extends AbstractUnitTest { assertEquals(0, constraints.getForeignKeys().size()); } + @Test + public void createTable_enumsSets_succeeds() throws DataServiceException, + DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, + TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException, + OntologyNotFoundException, SemanticEntityNotFoundException { + final CreateTableDto request = CreateTableDto.builder() + .name("New Table") + .description("A wonderful table") + .columns(new LinkedList<>(List.of(CreateTableColumnDto.builder() + .name("sex") + .type(ColumnTypeDto.ENUM) // <<< + .enums(new LinkedList<>(List.of("male", "female", "other"))) + .build(), + CreateTableColumnDto.builder() + .name("status") + .type(ColumnTypeDto.SET) // <<< + .sets(new LinkedList<>(List.of("single", "married", "divorced", "widowed"))) + .build()))) + .constraints(CreateTableConstraintsDto.builder() + .checks(Set.of()) + .uniques(List.of()) + .foreignKeys(List.of()) + .primaryKey(Set.of()) + .build()) + .build(); + + /* mock */ + when(userService.findByUsername(USER_1_USERNAME)) + .thenReturn(USER_1); + doNothing() + .when(dataServiceGateway) + .createTable(eq(DATABASE_1_ID), any(CreateTableDto.class)); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + when(searchServiceGateway.update(any(Database.class))) + .thenReturn(DATABASE_1_BRIEF_DTO); + + /* test */ + final Table response = tableService.createTable(DATABASE_1, request, USER_1_PRINCIPAL); + final TableColumn column0 = response.getColumns().get(0); + assertEquals("sex", column0.getInternalName()); + assertEquals(TableColumnType.ENUM, column0.getColumnType()); + assertEquals(List.of("male", "female", "other"), column0.getEnums().stream().map(ColumnEnum::getValue).toList()); + final TableColumn column1 = response.getColumns().get(1); + assertEquals("status", column1.getInternalName()); + assertEquals(List.of("single", "married", "divorced", "widowed"), column1.getSets().stream().map(ColumnSet::getValue).toList()); + } + @Test public void createTable_dateFormatNotFound_fails() throws DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, @@ -377,6 +428,23 @@ public class TableServiceUnitTest extends AbstractUnitTest { }); } + @Test + public void updateTable_succeeds() throws DataServiceException, DataServiceConnectionException, + TableNotFoundException, DatabaseNotFoundException, SearchServiceException, + SearchServiceConnectionException { + + /* mock */ + doNothing() + .when(dataServiceGateway) + .updateTable(any(UUID.class), any(UUID.class), any(TableUpdateDto.class)); + when(searchServiceGateway.update(any(Database.class))) + .thenReturn(DATABASE_3_BRIEF_DTO); + + /* test */ + final Table response = tableService.updateTable(TABLE_8, TABLE_8_UPDATE_DTO); + assertNotNull(response.getId()); + } + @Test public void create_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java index 75fab311dd..e99fef1acc 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java @@ -50,10 +50,11 @@ public class ViewServiceUnitTest extends AbstractUnitTest { @Test public void create_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { + DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, TableNotFoundException, + ImageNotFoundException { final CreateViewDto request = CreateViewDto.builder() .name(VIEW_1_NAME) - .query(VIEW_1_QUERY) + .query(VIEW_1_SUBSET_DTO) .isPublic(VIEW_1_PUBLIC) .build(); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java index a5769ea986..54c9dd80bf 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/ViewService.java @@ -54,7 +54,7 @@ public interface ViewService { */ View create(Database database, User user, CreateViewDto data) throws MalformedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException; + SearchServiceConnectionException, TableNotFoundException, ImageNotFoundException; /** * @param database diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java index 6df1265b75..0ec24ad0d0 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java @@ -114,20 +114,24 @@ public class TableServiceImpl implements TableService { for (int i = 0; i < data.getColumns().size(); i++) { final CreateTableColumnDto c = data.getColumns().get(i); final TableColumn column = metadataMapper.columnCreateDtoToTableColumn(c, database.getContainer().getImage()); - column.setEnums(c.getEnums() - .stream() - .map(e -> ColumnEnum.builder() - .column(column) - .value(e) - .build()) - .toList()); - column.setSets(c.getSets() - .stream() - .map(e -> ColumnSet.builder() - .column(column) - .value(e) - .build()) - .toList()); + if (c.getEnums() != null) { + column.setEnums(c.getEnums() + .stream() + .map(e -> ColumnEnum.builder() + .column(column) + .value(e) + .build()) + .toList()); + } + if (c.getSets() != null) { + column.setSets(c.getSets() + .stream() + .map(e -> ColumnSet.builder() + .column(column) + .value(e) + .build()) + .toList()); + } column.setOrdinalPosition(idx[0]++); column.setTable(table); if (c.getUnitUri() != null) { diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java index 7bb45d568e..51c9832e26 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java @@ -90,7 +90,7 @@ public class ViewServiceImpl implements ViewService { @Transactional public View create(Database database, User creator, CreateViewDto data) throws MalformedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException { + SearchServiceConnectionException, TableNotFoundException, ImageNotFoundException { /* create in metadata database */ final View view = View.builder() .database(database) @@ -99,10 +99,6 @@ public class ViewServiceImpl implements ViewService { .ownedBy(creator.getId()) .owner(creator) .identifiers(new LinkedList<>()) - .query(data.getQuery()) - .queryHash(Hashing.sha256() - .hashString(data.getQuery(), StandardCharsets.UTF_8) - .toString()) .columns(new LinkedList<>()) .isInitialView(false) .isSchemaPublic(data.getIsSchemaPublic()) @@ -117,6 +113,10 @@ public class ViewServiceImpl implements ViewService { .toList()); view.getColumns() .forEach(column -> column.setView(view)); + view.setQuery(rawView.getQuery()); + view.setQueryHash(Hashing.sha256() + .hashString(rawView.getQuery(), StandardCharsets.UTF_8) + .toString()); database.getViews() .add(view); database = databaseRepository.save(database); diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java index b5da835fa1..e7051486db 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java @@ -12,6 +12,7 @@ import at.tuwien.api.container.image.*; import at.tuwien.api.database.*; import at.tuwien.api.database.query.QueryBriefDto; import at.tuwien.api.database.query.QueryDto; +import at.tuwien.api.database.query.SubsetDto; import at.tuwien.api.database.table.*; import at.tuwien.api.database.table.columns.*; import at.tuwien.api.database.table.columns.concepts.*; @@ -4968,7 +4969,7 @@ public abstract class BaseTest { public static final String VIEW_1_INTERNAL_NAME = "junit"; public static final Boolean VIEW_1_PUBLIC = false; public static final Boolean VIEW_1_SCHEMA_PUBLIC = false; - public static final String VIEW_1_QUERY = "select `location`, `lat`, `lng` from `weather_location`"; + public static final String VIEW_1_QUERY = "SELECT `location`, `lat`, `lng` FROM `weather_location`"; public static final String VIEW_1_QUERY_HASH = "dc81a6877c7c51a6a6f406e1fc2a255e44a0d49a20548596e0d583c3eb849c23"; public static final UUID VIEW_COLUMN_1_1_ID = UUID.fromString("ebf2c5ce-4deb-4cc6-b6f6-61f5d3f6fc98"); @@ -4977,6 +4978,11 @@ public abstract class BaseTest { public static final UUID VIEW_COLUMN_1_3_ID = UUID.fromString("4f189a5f-c9ca-4518-9758-1a0730f6276b"); + public static final SubsetDto VIEW_1_SUBSET_DTO = SubsetDto.builder() + .tableId(TABLE_2_ID) + .columns(new LinkedList<>(List.of(COLUMN_2_1_ID, COLUMN_2_2_ID, COLUMN_2_3_ID))) + .build(); + public static final List<ViewColumnDto> VIEW_1_COLUMNS_DTO = List.of( ViewColumnDto.builder() .id(VIEW_COLUMN_1_1_ID) @@ -5128,7 +5134,7 @@ public abstract class BaseTest { public static final CreateViewDto VIEW_1_CREATE_DTO = CreateViewDto.builder() .isPublic(VIEW_1_PUBLIC) .name(VIEW_1_NAME) - .query(VIEW_1_QUERY) + .query(VIEW_1_SUBSET_DTO) .build(); public static final UUID VIEW_2_ID = UUID.fromString("1921a0a0-e4b0-4d12-a05f-be920af9b5ce"); diff --git a/lib/python/dbrepo/api/dto.py b/lib/python/dbrepo/api/dto.py index d004a9faa3..71793471e7 100644 --- a/lib/python/dbrepo/api/dto.py +++ b/lib/python/dbrepo/api/dto.py @@ -35,6 +35,7 @@ class ImageBrief(BaseModel): id: str name: str version: str + default: bool class CreateDatabase(BaseModel): diff --git a/lib/python/tests/test_unit_container.py b/lib/python/tests/test_unit_container.py index 1faf4ec738..2033e2aa55 100644 --- a/lib/python/tests/test_unit_container.py +++ b/lib/python/tests/test_unit_container.py @@ -26,9 +26,12 @@ class ContainerUnitTest(unittest.TestCase): driver_class="org.mariadb.jdbc.Driver", jdbc_method="mariadb", data_types=[ - DataType(display_name="SERIAL", value="serial", + DataType(id="22975809-5496-4d67-9fd4-6689f0030f82", + display_name="SERIAL", + value="serial", documentation="https://mariadb.com/kb/en/bigint/", - is_quoted=False, is_buildable=True)])) + is_quoted=False, + is_buildable=True)])) # mock mock.post('/api/container', json=exp.model_dump(), status_code=201) # test @@ -177,9 +180,12 @@ class ContainerUnitTest(unittest.TestCase): driver_class="org.mariadb.jdbc.Driver", jdbc_method="mariadb", data_types=[ - DataType(display_name="SERIAL", value="serial", + DataType(id="22975809-5496-4d67-9fd4-6689f0030f82", + display_name="SERIAL", + value="serial", documentation="https://mariadb.com/kb/en/bigint/", - is_quoted=False, is_buildable=True)])) + is_quoted=False, + is_buildable=True)])) # mock mock.get('/api/container/44d811a8-4019-46ba-bd57-ea10a2eb0c74', json=exp.model_dump()) # test diff --git a/lib/python/tests/test_unit_image.py b/lib/python/tests/test_unit_image.py index 2802efc690..c350240c4e 100644 --- a/lib/python/tests/test_unit_image.py +++ b/lib/python/tests/test_unit_image.py @@ -19,7 +19,10 @@ class ImageUnitTest(unittest.TestCase): def test_get_images_succeeds(self): with requests_mock.Mocker() as mock: - exp = [ImageBrief(id=1, name="mariadb", version="11.1.3", jdbc_method="mariadb", default=False)] + exp = [ImageBrief(id="96c1876a-7473-44fd-8115-19ca6fde32d4", + name="mariadb", + version="11.1.3", + default=False)] # mock mock.get('/api/image', json=[exp[0].model_dump()]) # test diff --git a/lib/python/tests/test_unit_messages.py b/lib/python/tests/test_unit_messages.py index cf863dcb6c..b5fe7742c9 100644 --- a/lib/python/tests/test_unit_messages.py +++ b/lib/python/tests/test_unit_messages.py @@ -19,7 +19,7 @@ class ImageUnitTest(unittest.TestCase): def test_get_images_succeeds(self): with requests_mock.Mocker() as mock: - exp = [Message(id=1, type="info")] + exp = [Message(id="a456d7f0-9d42-48a8-bf5b-4ead85279e0e", type="info")] # mock mock.get('/api/message', json=[exp[0].model_dump()]) # test -- GitLab From 3438f2ae829fddb18f50d67856ba45ff7932a688 Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Tue, 25 Feb 2025 11:13:32 +0100 Subject: [PATCH 02/11] Fixed a test Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- lib/python/coverage.xml | 468 ++++++++++++++---------- lib/python/dbrepo/api/dto.py | 17 +- lib/python/tests/test_unit_container.py | 17 +- lib/python/tests/test_unit_database.py | 353 ++++++++++-------- 4 files changed, 495 insertions(+), 360 deletions(-) diff --git a/lib/python/coverage.xml b/lib/python/coverage.xml index 4c3ca2d895..ac21b0bc1e 100644 --- a/lib/python/coverage.xml +++ b/lib/python/coverage.xml @@ -1,14 +1,14 @@ <?xml version="1.0" ?> -<coverage version="7.6.12" timestamp="1740131337201" lines-valid="1752" lines-covered="1699" line-rate="0.9697" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0"> - <!-- Generated by coverage.py: https://coverage.readthedocs.io/en/7.6.12 --> +<coverage version="7.6.10" timestamp="1740478405603" lines-valid="1820" lines-covered="1743" line-rate="0.9577" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0"> + <!-- Generated by coverage.py: https://coverage.readthedocs.io/en/7.6.10 --> <!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd --> <sources> <source>/home/mweise/Projects/fda-services/lib/python</source> </sources> <packages> - <package name="dbrepo" line-rate="0.9376" branch-rate="0" complexity="0"> + <package name="dbrepo" line-rate="0.9134" branch-rate="0" complexity="0"> <classes> - <class name="RestClient.py" filename="dbrepo/RestClient.py" complexity="0" line-rate="0.9503" branch-rate="0"> + <class name="RestClient.py" filename="dbrepo/RestClient.py" complexity="0" line-rate="0.9248" branch-rate="0"> <methods/> <lines> <line number="1" hits="1"/> @@ -783,27 +783,20 @@ <line number="1679" hits="1"/> <line number="1680" hits="1"/> <line number="1683" hits="1"/> - <line number="1689" hits="1"/> - <line number="1690" hits="1"/> - <line number="1691" hits="1"/> - <line number="1692" hits="1"/> - <line number="1693" hits="1"/> - <line number="1694" hits="1"/> + <line number="1689" hits="0"/> + <line number="1690" hits="0"/> + <line number="1691" hits="0"/> + <line number="1692" hits="0"/> + <line number="1693" hits="0"/> + <line number="1694" hits="0"/> <line number="1697" hits="1"/> - <line number="1716" hits="1"/> - <line number="1717" hits="1"/> - <line number="1718" hits="1"/> - <line number="1719" hits="1"/> - <line number="1720" hits="1"/> - <line number="1721" hits="1"/> - <line number="1722" hits="1"/> - <line number="1723" hits="1"/> - <line number="1724" hits="1"/> - <line number="1725" hits="1"/> - <line number="1726" hits="1"/> - <line number="1727" hits="1"/> - <line number="1728" hits="1"/> - <line number="1729" hits="1"/> + <line number="1703" hits="1"/> + <line number="1704" hits="1"/> + <line number="1705" hits="1"/> + <line number="1706" hits="1"/> + <line number="1707" hits="1"/> + <line number="1708" hits="1"/> + <line number="1711" hits="1"/> <line number="1730" hits="1"/> <line number="1731" hits="1"/> <line number="1732" hits="1"/> @@ -818,24 +811,70 @@ <line number="1741" hits="1"/> <line number="1742" hits="1"/> <line number="1743" hits="1"/> + <line number="1744" hits="1"/> <line number="1745" hits="1"/> + <line number="1746" hits="1"/> + <line number="1747" hits="1"/> <line number="1748" hits="1"/> - <line number="1768" hits="1"/> - <line number="1769" hits="1"/> - <line number="1771" hits="1"/> - <line number="1772" hits="1"/> - <line number="1773" hits="1"/> - <line number="1774" hits="1"/> - <line number="1775" hits="1"/> - <line number="1776" hits="1"/> - <line number="1777" hits="1"/> - <line number="1778" hits="1"/> - <line number="1779" hits="1"/> - <line number="1780" hits="1"/> - <line number="1781" hits="1"/> - <line number="1782" hits="1"/> + <line number="1749" hits="1"/> + <line number="1750" hits="1"/> + <line number="1751" hits="1"/> + <line number="1752" hits="1"/> + <line number="1753" hits="1"/> + <line number="1754" hits="1"/> + <line number="1755" hits="1"/> + <line number="1756" hits="1"/> + <line number="1757" hits="1"/> + <line number="1759" hits="1"/> + <line number="1762" hits="1"/> + <line number="1773" hits="0"/> + <line number="1774" hits="0"/> + <line number="1775" hits="0"/> + <line number="1776" hits="0"/> + <line number="1777" hits="0"/> + <line number="1778" hits="0"/> + <line number="1779" hits="0"/> + <line number="1780" hits="0"/> <line number="1783" hits="1"/> - <line number="1784" hits="1"/> + <line number="1794" hits="0"/> + <line number="1795" hits="0"/> + <line number="1796" hits="0"/> + <line number="1797" hits="0"/> + <line number="1798" hits="0"/> + <line number="1799" hits="0"/> + <line number="1800" hits="0"/> + <line number="1801" hits="0"/> + <line number="1804" hits="1"/> + <line number="1810" hits="1"/> + <line number="1811" hits="1"/> + <line number="1812" hits="1"/> + <line number="1813" hits="1"/> + <line number="1814" hits="1"/> + <line number="1815" hits="0"/> + <line number="1818" hits="1"/> + <line number="1824" hits="1"/> + <line number="1825" hits="1"/> + <line number="1826" hits="1"/> + <line number="1827" hits="1"/> + <line number="1828" hits="1"/> + <line number="1829" hits="0"/> + <line number="1833" hits="1"/> + <line number="1853" hits="1"/> + <line number="1854" hits="1"/> + <line number="1856" hits="1"/> + <line number="1857" hits="1"/> + <line number="1858" hits="1"/> + <line number="1859" hits="1"/> + <line number="1860" hits="1"/> + <line number="1861" hits="1"/> + <line number="1862" hits="1"/> + <line number="1863" hits="1"/> + <line number="1864" hits="1"/> + <line number="1865" hits="1"/> + <line number="1866" hits="1"/> + <line number="1867" hits="1"/> + <line number="1868" hits="1"/> + <line number="1869" hits="1"/> </lines> </class> <class name="UploadClient.py" filename="dbrepo/UploadClient.py" complexity="0" line-rate="0.52" branch-rate="0"> @@ -895,44 +934,44 @@ <line number="17" hits="1"/> <line number="18" hits="1"/> <line number="19" hits="1"/> - <line number="20" hits="1"/> - <line number="21" hits="1"/> <line number="22" hits="1"/> <line number="23" hits="1"/> <line number="24" hits="1"/> + <line number="25" hits="1"/> + <line number="26" hits="1"/> <line number="27" hits="1"/> <line number="28" hits="1"/> <line number="29" hits="1"/> <line number="30" hits="1"/> + <line number="31" hits="1"/> + <line number="32" hits="1"/> <line number="33" hits="1"/> - <line number="34" hits="1"/> - <line number="35" hits="1"/> <line number="36" hits="1"/> <line number="37" hits="1"/> + <line number="38" hits="1"/> + <line number="39" hits="1"/> <line number="40" hits="1"/> - <line number="41" hits="1"/> - <line number="42" hits="1"/> + <line number="43" hits="1"/> + <line number="44" hits="1"/> <line number="45" hits="1"/> <line number="46" hits="1"/> <line number="47" hits="1"/> - <line number="48" hits="1"/> - <line number="49" hits="1"/> <line number="50" hits="1"/> <line number="51" hits="1"/> <line number="52" hits="1"/> - <line number="53" hits="1"/> + <line number="55" hits="1"/> <line number="56" hits="1"/> <line number="57" hits="1"/> <line number="58" hits="1"/> <line number="59" hits="1"/> + <line number="60" hits="1"/> + <line number="61" hits="1"/> <line number="62" hits="1"/> <line number="63" hits="1"/> - <line number="64" hits="1"/> - <line number="65" hits="1"/> <line number="66" hits="1"/> <line number="67" hits="1"/> <line number="68" hits="1"/> - <line number="71" hits="1"/> + <line number="69" hits="1"/> <line number="72" hits="1"/> <line number="73" hits="1"/> <line number="74" hits="1"/> @@ -948,7 +987,7 @@ <line number="86" hits="1"/> <line number="87" hits="1"/> <line number="88" hits="1"/> - <line number="89" hits="1"/> + <line number="91" hits="1"/> <line number="92" hits="1"/> <line number="93" hits="1"/> <line number="94" hits="1"/> @@ -956,7 +995,7 @@ <line number="96" hits="1"/> <line number="97" hits="1"/> <line number="98" hits="1"/> - <line number="101" hits="1"/> + <line number="99" hits="1"/> <line number="102" hits="1"/> <line number="103" hits="1"/> <line number="104" hits="1"/> @@ -972,16 +1011,16 @@ <line number="116" hits="1"/> <line number="117" hits="1"/> <line number="118" hits="1"/> - <line number="119" hits="1"/> - <line number="120" hits="1"/> + <line number="121" hits="1"/> + <line number="122" hits="1"/> <line number="123" hits="1"/> <line number="124" hits="1"/> <line number="125" hits="1"/> <line number="126" hits="1"/> <line number="127" hits="1"/> + <line number="128" hits="1"/> + <line number="129" hits="1"/> <line number="130" hits="1"/> - <line number="131" hits="1"/> - <line number="132" hits="1"/> <line number="133" hits="1"/> <line number="134" hits="1"/> <line number="135" hits="1"/> @@ -989,26 +1028,24 @@ <line number="137" hits="1"/> <line number="140" hits="1"/> <line number="141" hits="1"/> + <line number="142" hits="1"/> + <line number="143" hits="1"/> <line number="144" hits="1"/> <line number="145" hits="1"/> - <line number="148" hits="1"/> - <line number="152" hits="1"/> - <line number="153" hits="1"/> + <line number="146" hits="1"/> + <line number="147" hits="1"/> + <line number="150" hits="1"/> + <line number="151" hits="1"/> + <line number="154" hits="1"/> <line number="155" hits="1"/> - <line number="156" hits="1"/> <line number="158" hits="1"/> - <line number="159" hits="1"/> <line number="162" hits="1"/> + <line number="163" hits="1"/> + <line number="165" hits="1"/> <line number="166" hits="1"/> - <line number="167" hits="1"/> <line number="168" hits="1"/> <line number="169" hits="1"/> - <line number="170" hits="1"/> - <line number="171" hits="1"/> <line number="172" hits="1"/> - <line number="173" hits="1"/> - <line number="174" hits="1"/> - <line number="175" hits="1"/> <line number="176" hits="1"/> <line number="177" hits="1"/> <line number="178" hits="1"/> @@ -1029,17 +1066,17 @@ <line number="193" hits="1"/> <line number="194" hits="1"/> <line number="195" hits="1"/> + <line number="196" hits="1"/> + <line number="197" hits="1"/> <line number="198" hits="1"/> + <line number="199" hits="1"/> + <line number="200" hits="1"/> + <line number="201" hits="1"/> <line number="202" hits="1"/> <line number="203" hits="1"/> <line number="204" hits="1"/> <line number="205" hits="1"/> - <line number="206" hits="1"/> - <line number="207" hits="1"/> <line number="208" hits="1"/> - <line number="209" hits="1"/> - <line number="210" hits="1"/> - <line number="211" hits="1"/> <line number="212" hits="1"/> <line number="213" hits="1"/> <line number="214" hits="1"/> @@ -1214,41 +1251,43 @@ <line number="383" hits="1"/> <line number="384" hits="1"/> <line number="385" hits="1"/> + <line number="386" hits="1"/> + <line number="387" hits="1"/> <line number="388" hits="1"/> <line number="389" hits="1"/> <line number="390" hits="1"/> + <line number="391" hits="1"/> + <line number="392" hits="1"/> <line number="393" hits="1"/> <line number="394" hits="1"/> - <line number="397" hits="1"/> + <line number="395" hits="1"/> <line number="398" hits="1"/> - <line number="401" hits="1"/> - <line number="405" hits="1"/> - <line number="406" hits="1"/> + <line number="399" hits="1"/> + <line number="400" hits="1"/> + <line number="403" hits="1"/> + <line number="404" hits="1"/> <line number="407" hits="1"/> <line number="408" hits="1"/> <line number="411" hits="1"/> - <line number="412" hits="1"/> - <line number="413" hits="1"/> - <line number="414" hits="1"/> + <line number="415" hits="1"/> + <line number="416" hits="1"/> <line number="417" hits="1"/> <line number="418" hits="1"/> <line number="421" hits="1"/> <line number="422" hits="1"/> <line number="423" hits="1"/> <line number="424" hits="1"/> - <line number="425" hits="1"/> + <line number="427" hits="1"/> <line number="428" hits="1"/> - <line number="429" hits="1"/> - <line number="430" hits="1"/> <line number="431" hits="1"/> + <line number="432" hits="1"/> + <line number="433" hits="1"/> <line number="434" hits="1"/> <line number="435" hits="1"/> <line number="438" hits="1"/> <line number="439" hits="1"/> <line number="440" hits="1"/> <line number="441" hits="1"/> - <line number="442" hits="1"/> - <line number="443" hits="1"/> <line number="444" hits="1"/> <line number="445" hits="1"/> <line number="448" hits="1"/> @@ -1258,8 +1297,10 @@ <line number="452" hits="1"/> <line number="453" hits="1"/> <line number="454" hits="1"/> - <line number="457" hits="1"/> + <line number="455" hits="1"/> <line number="458" hits="1"/> + <line number="459" hits="1"/> + <line number="460" hits="1"/> <line number="461" hits="1"/> <line number="462" hits="1"/> <line number="463" hits="1"/> @@ -1269,127 +1310,125 @@ <line number="471" hits="1"/> <line number="472" hits="1"/> <line number="473" hits="1"/> - <line number="476" hits="1"/> + <line number="474" hits="1"/> <line number="477" hits="1"/> + <line number="478" hits="1"/> + <line number="479" hits="1"/> <line number="480" hits="1"/> <line number="481" hits="1"/> <line number="482" hits="1"/> <line number="483" hits="1"/> - <line number="484" hits="1"/> - <line number="485" hits="1"/> - <line number="488" hits="1"/> - <line number="489" hits="1"/> + <line number="486" hits="1"/> + <line number="487" hits="1"/> <line number="490" hits="1"/> - <line number="493" hits="1"/> - <line number="494" hits="1"/> + <line number="491" hits="1"/> + <line number="492" hits="1"/> <line number="495" hits="1"/> - <line number="498" hits="1"/> + <line number="496" hits="1"/> <line number="499" hits="1"/> + <line number="500" hits="1"/> + <line number="501" hits="1"/> <line number="502" hits="1"/> <line number="503" hits="1"/> <line number="504" hits="1"/> - <line number="505" hits="1"/> - <line number="506" hits="1"/> <line number="507" hits="1"/> <line number="508" hits="1"/> - <line number="511" hits="1"/> + <line number="509" hits="1"/> <line number="512" hits="1"/> <line number="513" hits="1"/> <line number="514" hits="1"/> - <line number="515" hits="1"/> - <line number="516" hits="1"/> <line number="517" hits="1"/> <line number="518" hits="1"/> - <line number="519" hits="1"/> - <line number="520" hits="1"/> <line number="521" hits="1"/> <line number="522" hits="1"/> + <line number="523" hits="1"/> + <line number="524" hits="1"/> <line number="525" hits="1"/> <line number="526" hits="1"/> <line number="527" hits="1"/> - <line number="528" hits="1"/> - <line number="529" hits="1"/> + <line number="530" hits="1"/> + <line number="531" hits="1"/> <line number="532" hits="1"/> + <line number="533" hits="1"/> + <line number="534" hits="1"/> + <line number="535" hits="1"/> <line number="536" hits="1"/> <line number="537" hits="1"/> <line number="538" hits="1"/> <line number="539" hits="1"/> - <line number="542" hits="1"/> + <line number="540" hits="1"/> + <line number="541" hits="1"/> + <line number="544" hits="1"/> + <line number="545" hits="1"/> <line number="546" hits="1"/> <line number="547" hits="1"/> <line number="548" hits="1"/> <line number="551" hits="1"/> - <line number="552" hits="1"/> - <line number="553" hits="1"/> - <line number="554" hits="1"/> <line number="555" hits="1"/> <line number="556" hits="1"/> <line number="557" hits="1"/> <line number="558" hits="1"/> - <line number="559" hits="1"/> - <line number="560" hits="1"/> <line number="561" hits="1"/> - <line number="562" hits="1"/> - <line number="563" hits="1"/> + <line number="565" hits="1"/> <line number="566" hits="1"/> <line number="567" hits="1"/> - <line number="568" hits="1"/> - <line number="569" hits="1"/> <line number="570" hits="1"/> <line number="571" hits="1"/> <line number="572" hits="1"/> <line number="573" hits="1"/> <line number="574" hits="1"/> + <line number="575" hits="1"/> + <line number="576" hits="1"/> <line number="577" hits="1"/> <line number="578" hits="1"/> <line number="579" hits="1"/> <line number="580" hits="1"/> <line number="581" hits="1"/> <line number="582" hits="1"/> - <line number="583" hits="1"/> - <line number="584" hits="1"/> <line number="585" hits="1"/> <line number="586" hits="1"/> <line number="587" hits="1"/> <line number="588" hits="1"/> + <line number="589" hits="1"/> + <line number="590" hits="1"/> <line number="591" hits="1"/> <line number="592" hits="1"/> - <line number="595" hits="1"/> + <line number="593" hits="1"/> <line number="596" hits="1"/> <line number="597" hits="1"/> <line number="598" hits="1"/> <line number="599" hits="1"/> + <line number="600" hits="1"/> + <line number="601" hits="1"/> <line number="602" hits="1"/> <line number="603" hits="1"/> <line number="604" hits="1"/> <line number="605" hits="1"/> - <line number="608" hits="1"/> - <line number="609" hits="1"/> - <line number="612" hits="1"/> - <line number="613" hits="1"/> + <line number="606" hits="1"/> + <line number="607" hits="1"/> + <line number="610" hits="1"/> + <line number="611" hits="1"/> <line number="614" hits="1"/> <line number="615" hits="1"/> <line number="616" hits="1"/> <line number="617" hits="1"/> <line number="618" hits="1"/> - <line number="619" hits="1"/> - <line number="620" hits="1"/> <line number="621" hits="1"/> <line number="622" hits="1"/> <line number="623" hits="1"/> <line number="624" hits="1"/> - <line number="625" hits="1"/> - <line number="626" hits="1"/> <line number="627" hits="1"/> <line number="628" hits="1"/> - <line number="629" hits="1"/> - <line number="630" hits="1"/> <line number="631" hits="1"/> <line number="632" hits="1"/> <line number="633" hits="1"/> <line number="634" hits="1"/> + <line number="635" hits="1"/> + <line number="636" hits="1"/> <line number="637" hits="1"/> <line number="638" hits="1"/> + <line number="639" hits="1"/> + <line number="640" hits="1"/> <line number="641" hits="1"/> <line number="642" hits="1"/> <line number="643" hits="1"/> @@ -1403,12 +1442,8 @@ <line number="651" hits="1"/> <line number="652" hits="1"/> <line number="653" hits="1"/> - <line number="654" hits="1"/> - <line number="655" hits="1"/> <line number="656" hits="1"/> <line number="657" hits="1"/> - <line number="658" hits="1"/> - <line number="659" hits="1"/> <line number="660" hits="1"/> <line number="661" hits="1"/> <line number="662" hits="1"/> @@ -1416,6 +1451,8 @@ <line number="664" hits="1"/> <line number="665" hits="1"/> <line number="666" hits="1"/> + <line number="667" hits="1"/> + <line number="668" hits="1"/> <line number="669" hits="1"/> <line number="670" hits="1"/> <line number="671" hits="1"/> @@ -1429,10 +1466,10 @@ <line number="679" hits="1"/> <line number="680" hits="1"/> <line number="681" hits="1"/> + <line number="682" hits="1"/> + <line number="683" hits="1"/> <line number="684" hits="1"/> <line number="685" hits="1"/> - <line number="686" hits="1"/> - <line number="687" hits="1"/> <line number="688" hits="1"/> <line number="689" hits="1"/> <line number="690" hits="1"/> @@ -1440,13 +1477,15 @@ <line number="692" hits="1"/> <line number="693" hits="1"/> <line number="694" hits="1"/> - <line number="695" hits="1"/> - <line number="696" hits="1"/> + <line number="697" hits="1"/> + <line number="698" hits="1"/> <line number="699" hits="1"/> <line number="700" hits="1"/> <line number="701" hits="1"/> <line number="702" hits="1"/> <line number="703" hits="1"/> + <line number="704" hits="1"/> + <line number="705" hits="1"/> <line number="706" hits="1"/> <line number="707" hits="1"/> <line number="708" hits="1"/> @@ -1462,68 +1501,67 @@ <line number="720" hits="1"/> <line number="721" hits="1"/> <line number="722" hits="1"/> - <line number="725" hits="1"/> - <line number="726" hits="1"/> + <line number="723" hits="1"/> + <line number="724" hits="1"/> <line number="727" hits="1"/> <line number="728" hits="1"/> <line number="729" hits="1"/> - <line number="732" hits="1"/> - <line number="733" hits="1"/> + <line number="730" hits="1"/> + <line number="731" hits="1"/> <line number="734" hits="1"/> <line number="735" hits="1"/> - <line number="738" hits="1"/> - <line number="739" hits="1"/> + <line number="736" hits="1"/> + <line number="737" hits="1"/> + <line number="740" hits="1"/> + <line number="741" hits="1"/> <line number="742" hits="1"/> <line number="743" hits="1"/> <line number="744" hits="1"/> <line number="745" hits="1"/> <line number="746" hits="1"/> <line number="747" hits="1"/> + <line number="748" hits="1"/> + <line number="749" hits="1"/> <line number="750" hits="1"/> - <line number="751" hits="1"/> - <line number="752" hits="1"/> <line number="753" hits="1"/> + <line number="754" hits="1"/> + <line number="755" hits="1"/> <line number="756" hits="1"/> <line number="757" hits="1"/> <line number="760" hits="1"/> <line number="761" hits="1"/> <line number="762" hits="1"/> <line number="763" hits="1"/> - <line number="764" hits="1"/> + <line number="766" hits="1"/> <line number="767" hits="1"/> - <line number="768" hits="1"/> + <line number="770" hits="1"/> <line number="771" hits="1"/> + <line number="772" hits="1"/> + <line number="773" hits="1"/> + <line number="774" hits="1"/> <line number="775" hits="1"/> - <line number="776" hits="1"/> - <line number="777" hits="1"/> <line number="778" hits="1"/> + <line number="779" hits="1"/> + <line number="780" hits="1"/> <line number="781" hits="1"/> + <line number="784" hits="1"/> <line number="785" hits="1"/> - <line number="786" hits="1"/> + <line number="788" hits="1"/> <line number="789" hits="1"/> - <line number="793" hits="1"/> - <line number="794" hits="1"/> + <line number="790" hits="1"/> + <line number="791" hits="1"/> + <line number="792" hits="1"/> <line number="795" hits="1"/> <line number="796" hits="1"/> - <line number="797" hits="1"/> - <line number="798" hits="1"/> <line number="799" hits="1"/> - <line number="800" hits="1"/> - <line number="801" hits="1"/> - <line number="802" hits="1"/> <line number="803" hits="1"/> <line number="804" hits="1"/> <line number="805" hits="1"/> <line number="806" hits="1"/> - <line number="807" hits="1"/> - <line number="808" hits="1"/> <line number="809" hits="1"/> - <line number="810" hits="1"/> <line number="813" hits="1"/> + <line number="814" hits="1"/> <line number="817" hits="1"/> - <line number="818" hits="1"/> - <line number="819" hits="1"/> - <line number="820" hits="1"/> <line number="821" hits="1"/> <line number="822" hits="1"/> <line number="823" hits="1"/> @@ -1542,37 +1580,46 @@ <line number="836" hits="1"/> <line number="837" hits="1"/> <line number="838" hits="1"/> - <line number="839" hits="1"/> - <line number="840" hits="1"/> <line number="841" hits="1"/> - <line number="842" hits="1"/> - <line number="843" hits="1"/> - <line number="844" hits="1"/> <line number="845" hits="1"/> <line number="846" hits="1"/> <line number="847" hits="1"/> <line number="848" hits="1"/> <line number="849" hits="1"/> <line number="850" hits="1"/> + <line number="851" hits="1"/> + <line number="852" hits="1"/> <line number="853" hits="1"/> + <line number="854" hits="1"/> + <line number="855" hits="1"/> + <line number="856" hits="1"/> <line number="857" hits="1"/> <line number="858" hits="1"/> <line number="859" hits="1"/> <line number="860" hits="1"/> <line number="861" hits="1"/> <line number="862" hits="1"/> + <line number="863" hits="1"/> + <line number="864" hits="1"/> <line number="865" hits="1"/> + <line number="866" hits="1"/> + <line number="867" hits="1"/> + <line number="868" hits="1"/> <line number="869" hits="1"/> <line number="870" hits="1"/> + <line number="871" hits="1"/> <line number="872" hits="1"/> <line number="873" hits="1"/> + <line number="874" hits="1"/> + <line number="875" hits="1"/> <line number="876" hits="1"/> - <line number="880" hits="1"/> + <line number="877" hits="1"/> + <line number="878" hits="1"/> <line number="881" hits="1"/> - <line number="883" hits="1"/> - <line number="884" hits="1"/> + <line number="885" hits="1"/> <line number="886" hits="1"/> <line number="887" hits="1"/> + <line number="888" hits="1"/> <line number="889" hits="1"/> <line number="890" hits="1"/> <line number="893" hits="1"/> @@ -1590,29 +1637,19 @@ <line number="917" hits="1"/> <line number="918" hits="1"/> <line number="921" hits="1"/> - <line number="922" hits="1"/> - <line number="923" hits="1"/> - <line number="924" hits="1"/> <line number="925" hits="1"/> <line number="926" hits="1"/> - <line number="927" hits="1"/> <line number="928" hits="1"/> <line number="929" hits="1"/> - <line number="930" hits="1"/> - <line number="931" hits="1"/> <line number="932" hits="1"/> - <line number="933" hits="1"/> <line number="936" hits="1"/> <line number="937" hits="1"/> + <line number="939" hits="1"/> <line number="940" hits="1"/> - <line number="941" hits="1"/> <line number="942" hits="1"/> <line number="943" hits="1"/> - <line number="944" hits="1"/> <line number="945" hits="1"/> <line number="946" hits="1"/> - <line number="947" hits="1"/> - <line number="948" hits="1"/> <line number="949" hits="1"/> <line number="950" hits="1"/> <line number="951" hits="1"/> @@ -1620,26 +1657,20 @@ <line number="953" hits="1"/> <line number="954" hits="1"/> <line number="955" hits="1"/> + <line number="956" hits="1"/> + <line number="957" hits="1"/> <line number="958" hits="1"/> <line number="959" hits="1"/> <line number="960" hits="1"/> <line number="961" hits="1"/> - <line number="962" hits="1"/> - <line number="963" hits="1"/> <line number="964" hits="1"/> <line number="965" hits="1"/> - <line number="966" hits="1"/> - <line number="967" hits="1"/> <line number="968" hits="1"/> <line number="969" hits="1"/> <line number="970" hits="1"/> - <line number="971" hits="1"/> - <line number="972" hits="1"/> <line number="973" hits="1"/> <line number="974" hits="1"/> <line number="975" hits="1"/> - <line number="976" hits="1"/> - <line number="977" hits="1"/> <line number="978" hits="1"/> <line number="979" hits="1"/> <line number="980" hits="1"/> @@ -1647,6 +1678,8 @@ <line number="982" hits="1"/> <line number="983" hits="1"/> <line number="984" hits="1"/> + <line number="985" hits="1"/> + <line number="986" hits="1"/> <line number="987" hits="1"/> <line number="988" hits="1"/> <line number="989" hits="1"/> @@ -1655,8 +1688,6 @@ <line number="992" hits="1"/> <line number="993" hits="1"/> <line number="994" hits="1"/> - <line number="995" hits="1"/> - <line number="996" hits="1"/> <line number="997" hits="1"/> <line number="998" hits="1"/> <line number="999" hits="1"/> @@ -1664,6 +1695,8 @@ <line number="1001" hits="1"/> <line number="1002" hits="1"/> <line number="1003" hits="1"/> + <line number="1004" hits="1"/> + <line number="1005" hits="1"/> <line number="1006" hits="1"/> <line number="1007" hits="1"/> <line number="1008" hits="1"/> @@ -1682,8 +1715,8 @@ <line number="1021" hits="1"/> <line number="1022" hits="1"/> <line number="1023" hits="1"/> - <line number="1024" hits="1"/> - <line number="1025" hits="1"/> + <line number="1026" hits="1"/> + <line number="1027" hits="1"/> <line number="1028" hits="1"/> <line number="1029" hits="1"/> <line number="1030" hits="1"/> @@ -1695,10 +1728,10 @@ <line number="1036" hits="1"/> <line number="1037" hits="1"/> <line number="1038" hits="1"/> + <line number="1039" hits="1"/> + <line number="1040" hits="1"/> <line number="1041" hits="1"/> <line number="1042" hits="1"/> - <line number="1043" hits="1"/> - <line number="1044" hits="1"/> <line number="1045" hits="1"/> <line number="1046" hits="1"/> <line number="1047" hits="1"/> @@ -1713,6 +1746,8 @@ <line number="1056" hits="1"/> <line number="1057" hits="1"/> <line number="1058" hits="1"/> + <line number="1059" hits="1"/> + <line number="1060" hits="1"/> <line number="1061" hits="1"/> <line number="1062" hits="1"/> <line number="1063" hits="1"/> @@ -1722,14 +1757,21 @@ <line number="1069" hits="1"/> <line number="1070" hits="1"/> <line number="1071" hits="1"/> + <line number="1072" hits="1"/> + <line number="1073" hits="1"/> <line number="1074" hits="1"/> - <line number="1078" hits="1"/> - <line number="1079" hits="1"/> + <line number="1075" hits="1"/> + <line number="1076" hits="1"/> + <line number="1077" hits="1"/> <line number="1080" hits="1"/> <line number="1081" hits="1"/> <line number="1082" hits="1"/> + <line number="1083" hits="1"/> + <line number="1084" hits="1"/> <line number="1085" hits="1"/> <line number="1086" hits="1"/> + <line number="1087" hits="1"/> + <line number="1088" hits="1"/> <line number="1089" hits="1"/> <line number="1090" hits="1"/> <line number="1091" hits="1"/> @@ -1738,21 +1780,47 @@ <line number="1094" hits="1"/> <line number="1095" hits="1"/> <line number="1096" hits="1"/> - <line number="1099" hits="1"/> + <line number="1097" hits="1"/> <line number="1100" hits="1"/> <line number="1101" hits="1"/> <line number="1102" hits="1"/> <line number="1103" hits="1"/> - <line number="1104" hits="1"/> + <line number="1106" hits="1"/> <line number="1107" hits="1"/> <line number="1108" hits="1"/> <line number="1109" hits="1"/> <line number="1110" hits="1"/> <line number="1113" hits="1"/> - <line number="1114" hits="1"/> - <line number="1115" hits="1"/> - <line number="1116" hits="1"/> <line number="1117" hits="1"/> + <line number="1118" hits="1"/> + <line number="1119" hits="1"/> + <line number="1120" hits="1"/> + <line number="1121" hits="1"/> + <line number="1124" hits="1"/> + <line number="1125" hits="1"/> + <line number="1128" hits="1"/> + <line number="1129" hits="1"/> + <line number="1130" hits="1"/> + <line number="1131" hits="1"/> + <line number="1132" hits="1"/> + <line number="1133" hits="1"/> + <line number="1134" hits="1"/> + <line number="1135" hits="1"/> + <line number="1138" hits="1"/> + <line number="1139" hits="1"/> + <line number="1140" hits="1"/> + <line number="1141" hits="1"/> + <line number="1142" hits="1"/> + <line number="1143" hits="1"/> + <line number="1146" hits="1"/> + <line number="1147" hits="1"/> + <line number="1148" hits="1"/> + <line number="1149" hits="1"/> + <line number="1152" hits="1"/> + <line number="1153" hits="1"/> + <line number="1154" hits="1"/> + <line number="1155" hits="1"/> + <line number="1156" hits="1"/> </lines> </class> <class name="exceptions.py" filename="dbrepo/api/exceptions.py" complexity="0" line-rate="1" branch-rate="0"> diff --git a/lib/python/dbrepo/api/dto.py b/lib/python/dbrepo/api/dto.py index 71793471e7..203a80f5c3 100644 --- a/lib/python/dbrepo/api/dto.py +++ b/lib/python/dbrepo/api/dto.py @@ -12,6 +12,13 @@ Timestamp = Annotated[ ] +class Operator(BaseModel): + id: str + display_name: str + value: str + documentation: str + + class Image(BaseModel): id: str registry: str @@ -21,16 +28,11 @@ class Image(BaseModel): driver_class: str jdbc_method: str default_port: int + default: bool data_types: List[DataType] = field(default_factory=list) + operators: List[Operator] = field(default_factory=list) - -class Operator(BaseModel): - id: str - display_name: str - value: str - documentation: str - class ImageBrief(BaseModel): id: str name: str @@ -682,6 +684,7 @@ class Identifier(BaseModel): publication_day: Optional[int] = None publication_month: Optional[int] = None + class Message(BaseModel): id: str type: str diff --git a/lib/python/tests/test_unit_container.py b/lib/python/tests/test_unit_container.py index 2033e2aa55..052e2aa524 100644 --- a/lib/python/tests/test_unit_container.py +++ b/lib/python/tests/test_unit_container.py @@ -3,7 +3,7 @@ import unittest import requests_mock from dbrepo.RestClient import RestClient -from dbrepo.api.dto import Container, Image, ContainerBrief, ImageBrief, DataType +from dbrepo.api.dto import Container, Image, ContainerBrief, ImageBrief, DataType, Operator from dbrepo.api.exceptions import ResponseCodeError, NotExistsError, AuthenticationError, MalformedError, \ ForbiddenError, NameExistsError @@ -25,6 +25,12 @@ class ContainerUnitTest(unittest.TestCase): dialect="org.hibernate.dialect.MariaDBDialect", driver_class="org.mariadb.jdbc.Driver", jdbc_method="mariadb", + default=True, + operators=[ + Operator(id="0917b17e-5d68-4ddf-94f6-f178f74a0dae", + display_name="XOR", + value="XOR", + documentation="https://mariadb.com/kb/en/xor/")], data_types=[ DataType(id="22975809-5496-4d67-9fd4-6689f0030f82", display_name="SERIAL", @@ -145,7 +151,8 @@ class ContainerUnitTest(unittest.TestCase): running=True, image=ImageBrief(id="b104648b-54d2-4d72-9834-8e0e6d428b39", name="mariadb", - version="10.11.3"), + version="10.11.3", + default=True), hash="f829dd8a884182d0da846f365dee1221fd16610a14c81b8f9f295ff162749e50") ] # mock @@ -179,6 +186,12 @@ class ContainerUnitTest(unittest.TestCase): dialect="org.hibernate.dialect.MariaDBDialect", driver_class="org.mariadb.jdbc.Driver", jdbc_method="mariadb", + default=True, + operators=[ + Operator(id="0917b17e-5d68-4ddf-94f6-f178f74a0dae", + display_name="XOR", + value="XOR", + documentation="https://mariadb.com/kb/en/xor/")], data_types=[ DataType(id="22975809-5496-4d67-9fd4-6689f0030f82", display_name="SERIAL", diff --git a/lib/python/tests/test_unit_database.py b/lib/python/tests/test_unit_database.py index 3fd7ddcd60..54a41cfbd7 100644 --- a/lib/python/tests/test_unit_database.py +++ b/lib/python/tests/test_unit_database.py @@ -83,8 +83,8 @@ class DatabaseUnitTest(unittest.TestCase): image=ImageBrief( id="b104648b-54d2-4d72-9834-8e0e6d428b39", name='mariadb', - version='11.2.2' - ) + version='11.2.2', + default=True) ) ) with requests_mock.Mocker() as mock: @@ -100,7 +100,7 @@ class DatabaseUnitTest(unittest.TestCase): mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732', status_code=403) # test try: - response = RestClient().get_database(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient().get_database(database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ForbiddenError as e: pass @@ -110,7 +110,7 @@ class DatabaseUnitTest(unittest.TestCase): mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732', status_code=404) # test try: - response = RestClient().get_database(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient().get_database(database_id="6bd39359-b154-456d-b9c2-caa516a45732") except NotExistsError as e: pass @@ -120,7 +120,7 @@ class DatabaseUnitTest(unittest.TestCase): mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732', status_code=202) # test try: - response = RestClient().get_database(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient().get_database(database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ResponseCodeError as e: pass @@ -141,8 +141,8 @@ class DatabaseUnitTest(unittest.TestCase): image=ImageBrief( id="b104648b-54d2-4d72-9834-8e0e6d428b39", name='mariadb', - version='11.2.2' - ) + version='11.2.2', + default=True) ) ) with requests_mock.Mocker() as mock: @@ -161,9 +161,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.post('/api/database', status_code=400) # test try: - response = RestClient(username="a", password="b").create_database(name='test', - container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", - is_public=True) + RestClient(username="a", password="b").create_database(name='test', + container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", + is_public=True) except MalformedError as e: pass @@ -173,9 +173,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.post('/api/database', status_code=403) # test try: - response = RestClient(username="a", password="b").create_database(name='test', - container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", - is_public=True) + RestClient(username="a", password="b").create_database(name='test', + container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", + is_public=True) except ForbiddenError as e: pass @@ -185,9 +185,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.post('/api/database', status_code=404) # test try: - response = RestClient(username="a", password="b").create_database(name='test', - container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", - is_public=True) + RestClient(username="a", password="b").create_database(name='test', + container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", + is_public=True) except NotExistsError as e: pass @@ -197,9 +197,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.post('/api/database', status_code=409) # test try: - response = RestClient(username="a", password="b").create_database(name='test', - container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", - is_public=True) + RestClient(username="a", password="b").create_database(name='test', + container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", + is_public=True) except QueryStoreError as e: pass @@ -209,9 +209,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.post('/api/database', status_code=502) # test try: - response = RestClient(username="a", password="b").create_database(name='test', - container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", - is_public=True) + RestClient(username="a", password="b").create_database(name='test', + container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", + is_public=True) except ServiceConnectionError as e: pass @@ -221,9 +221,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.post('/api/database', status_code=503) # test try: - response = RestClient(username="a", password="b").create_database(name='test', - container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", - is_public=True) + RestClient(username="a", password="b").create_database(name='test', + container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", + is_public=True) except ServiceError as e: pass @@ -233,9 +233,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.post('/api/database', status_code=202) # test try: - response = RestClient(username="a", password="b").create_database(name='test', - container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", - is_public=True) + RestClient(username="a", password="b").create_database(name='test', + container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", + is_public=True) except ResponseCodeError as e: pass @@ -245,9 +245,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.post('/api/database', status_code=404) # test try: - response = RestClient().create_database(name='test', - container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", - is_public=True) + RestClient().create_database(name='test', + container_id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", + is_public=True) except AuthenticationError as e: pass @@ -268,8 +268,8 @@ class DatabaseUnitTest(unittest.TestCase): image=ImageBrief( id="b104648b-54d2-4d72-9834-8e0e6d428b39", name='mariadb', - version='11.2.2' - ) + version='11.2.2', + default=True) ) ) with requests_mock.Mocker() as mock: @@ -277,10 +277,10 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/visibility', json=exp.model_dump(), status_code=202) # test - client = RestClient(username="a", password="b") - response = RestClient(username="a", password="b").update_database_visibility(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - is_public=True, - is_schema_public=True) + response = RestClient(username="a", password="b").update_database_visibility( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + is_public=True, + is_schema_public=True) self.assertEqual(response.is_public, True) def test_update_database_visibility_400_fails(self): @@ -289,9 +289,10 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/visibility', status_code=400) # test try: - response = RestClient(username="a", password="b").update_database_visibility(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - is_public=True, - is_schema_public=True) + RestClient(username="a", password="b").update_database_visibility( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + is_public=True, + is_schema_public=True) except MalformedError: pass @@ -301,9 +302,10 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/visibility', status_code=403) # test try: - response = RestClient(username="a", password="b").update_database_visibility(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - is_public=True, - is_schema_public=True) + response = RestClient(username="a", password="b").update_database_visibility( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + is_public=True, + is_schema_public=True) except ForbiddenError: pass @@ -313,9 +315,10 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/visibility', status_code=404) # test try: - response = RestClient(username="a", password="b").update_database_visibility(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - is_public=True, - is_schema_public=True) + response = RestClient(username="a", password="b").update_database_visibility( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + is_public=True, + is_schema_public=True) except NotExistsError: pass @@ -325,9 +328,10 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/visibility', status_code=502) # test try: - response = RestClient(username="a", password="b").update_database_visibility(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - is_public=True, - is_schema_public=True) + RestClient(username="a", password="b").update_database_visibility( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + is_public=True, + is_schema_public=True) except ServiceConnectionError: pass @@ -337,9 +341,10 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/visibility', status_code=503) # test try: - response = RestClient(username="a", password="b").update_database_visibility(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - is_public=True, - is_schema_public=True) + RestClient(username="a", password="b").update_database_visibility( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + is_public=True, + is_schema_public=True) except ServiceError: pass @@ -349,16 +354,18 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/visibility', status_code=200) # test try: - response = RestClient(username="a", password="b").update_database_visibility(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - is_public=True, - is_schema_public=True) + RestClient(username="a", password="b").update_database_visibility( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + is_public=True, + is_schema_public=True) except ResponseCodeError: pass def test_update_database_visibility_anonymous_fails(self): # test try: - response = RestClient().update_database_visibility(database_id="6bd39359-b154-456d-b9c2-caa516a45732", is_public=True, is_schema_public=True) + RestClient().update_database_visibility(database_id="6bd39359-b154-456d-b9c2-caa516a45732", + is_public=True, is_schema_public=True) except AuthenticationError: pass @@ -379,8 +386,8 @@ class DatabaseUnitTest(unittest.TestCase): image=ImageBrief( id="b104648b-54d2-4d72-9834-8e0e6d428b39", name='mariadb', - version='11.2.2' - ) + version='11.2.2', + default=True) ) ) with requests_mock.Mocker() as mock: @@ -388,8 +395,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/owner', json=exp.model_dump(), status_code=202) # test client = RestClient(username="a", password="b") - response = RestClient(username="a", password="b").update_database_owner(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + response = RestClient(username="a", password="b").update_database_owner( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') self.assertEqual(response.owner.id, 'abdbf897-e599-4e5a-a3f0-7529884ea011') def test_update_database_owner_400_fails(self): @@ -398,8 +406,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/owner', status_code=400) # test try: - response = RestClient(username="a", password="b").update_database_owner(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_owner( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except MalformedError: pass @@ -409,8 +418,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/owner', status_code=403) # test try: - response = RestClient(username="a", password="b").update_database_owner(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_owner( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ForbiddenError: pass @@ -420,8 +430,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/owner', status_code=404) # test try: - response = RestClient(username="a", password="b").update_database_owner(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_owner( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except NotExistsError: pass @@ -431,8 +442,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/owner', status_code=502) # test try: - response = RestClient(username="a", password="b").update_database_owner(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_owner( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ServiceConnectionError: pass @@ -442,8 +454,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/owner', status_code=503) # test try: - response = RestClient(username="a", password="b").update_database_owner(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_owner( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ServiceError: pass @@ -453,8 +466,9 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/owner', status_code=200) # test try: - response = RestClient(username="a", password="b").update_database_owner(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_owner( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ResponseCodeError: pass @@ -464,8 +478,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/owner', status_code=404) # test try: - response = RestClient().update_database_owner(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient().update_database_owner(database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except AuthenticationError: pass @@ -484,7 +498,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/table', json=exp.model_dump()) mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/view', json=exp.model_dump()) # test - response = RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + response = RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") self.assertEqual(exp, response) def test_update_database_schema_400_fails(self): @@ -493,7 +508,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/table', status_code=400) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except MalformedError: pass @@ -504,7 +520,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/view', status_code=400) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except MalformedError: pass @@ -514,7 +531,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/table', status_code=403) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ForbiddenError: pass @@ -525,7 +543,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/view', status_code=403) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ForbiddenError: pass @@ -535,7 +554,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/table', status_code=404) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except NotExistsError: pass @@ -546,7 +566,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/view', status_code=404) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except NotExistsError: pass @@ -556,7 +577,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/table', status_code=502) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ServiceConnectionError: pass @@ -567,7 +589,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/view', status_code=502) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ServiceConnectionError: pass @@ -577,7 +600,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/table', status_code=503) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ServiceError: pass @@ -588,7 +612,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/view', status_code=503) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ServiceError: pass @@ -598,7 +623,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/table', status_code=202) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ResponseCodeError: pass @@ -609,7 +635,8 @@ class DatabaseUnitTest(unittest.TestCase): mock.put('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/metadata/view', status_code=202) # test try: - RestClient(username='foo', password='bar').update_database_schema(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient(username='foo', password='bar').update_database_schema( + database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ResponseCodeError: pass @@ -636,7 +663,7 @@ class DatabaseUnitTest(unittest.TestCase): mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/access', status_code=403) # test try: - response = RestClient().get_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient().get_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ForbiddenError: pass @@ -646,7 +673,7 @@ class DatabaseUnitTest(unittest.TestCase): mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/access', status_code=404) # test try: - response = RestClient().get_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient().get_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732") except NotExistsError: pass @@ -656,7 +683,7 @@ class DatabaseUnitTest(unittest.TestCase): mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/access', status_code=202) # test try: - response = RestClient().get_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732") + RestClient().get_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732") except ResponseCodeError: pass @@ -669,9 +696,10 @@ class DatabaseUnitTest(unittest.TestCase): json=exp.model_dump(), status_code=202) # test - response = RestClient(username="a", password="b").create_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + response = RestClient(username="a", password="b").create_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') self.assertEqual(response, exp.type) def test_create_database_access_400_fails(self): @@ -681,9 +709,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=400) # test try: - response = RestClient(username="a", password="b").create_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").create_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except MalformedError: pass @@ -694,8 +723,9 @@ class DatabaseUnitTest(unittest.TestCase): status_code=400) # test try: - response = RestClient().create_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient().create_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except AuthenticationError: pass @@ -706,9 +736,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=403) # test try: - response = RestClient(username="a", password="b").create_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").create_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ForbiddenError: pass @@ -719,9 +750,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=404) # test try: - response = RestClient(username="a", password="b").create_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").create_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except NotExistsError: pass @@ -732,9 +764,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=502) # test try: - response = RestClient(username="a", password="b").create_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").create_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ServiceConnectionError: pass @@ -745,9 +778,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=503) # test try: - response = RestClient(username="a", password="b").create_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").create_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ServiceError: pass @@ -758,9 +792,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=200) # test try: - response = RestClient(username="a", password="b").create_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").create_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ResponseCodeError: pass @@ -773,9 +808,10 @@ class DatabaseUnitTest(unittest.TestCase): json=exp.model_dump(), status_code=202) # test - response = RestClient(username="a", password="b").update_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + response = RestClient(username="a", password="b").update_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') self.assertEqual(response, exp.type) def test_update_database_access_400_fails(self): @@ -785,9 +821,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=400) # test try: - response = RestClient(username="a", password="b").update_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except MalformedError: pass @@ -798,9 +835,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=403) # test try: - response = RestClient(username="a", password="b").update_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ForbiddenError: pass @@ -811,9 +849,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=404) # test try: - response = RestClient(username="a", password="b").update_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except NotExistsError: pass @@ -824,9 +863,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=502) # test try: - response = RestClient(username="a", password="b").update_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ServiceConnectionError: pass @@ -837,9 +877,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=503) # test try: - response = RestClient(username="a", password="b").update_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ServiceError: pass @@ -850,9 +891,10 @@ class DatabaseUnitTest(unittest.TestCase): status_code=200) # test try: - response = RestClient(username="a", password="b").update_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").update_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ResponseCodeError: pass @@ -863,8 +905,9 @@ class DatabaseUnitTest(unittest.TestCase): status_code=404) # test try: - response = RestClient().update_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", type=AccessType.READ, - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient().update_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", + type=AccessType.READ, + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except AuthenticationError: pass @@ -876,8 +919,9 @@ class DatabaseUnitTest(unittest.TestCase): status_code=202) # test client = RestClient(username="a", password="b") - RestClient(username="a", password="b").delete_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").delete_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') def test_delete_database_access_400_fails(self): with requests_mock.Mocker() as mock: @@ -887,8 +931,9 @@ class DatabaseUnitTest(unittest.TestCase): status_code=400) # test try: - RestClient(username="a", password="b").delete_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").delete_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except MalformedError: pass @@ -900,8 +945,9 @@ class DatabaseUnitTest(unittest.TestCase): status_code=403) # test try: - RestClient(username="a", password="b").delete_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").delete_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ForbiddenError: pass @@ -913,8 +959,9 @@ class DatabaseUnitTest(unittest.TestCase): status_code=404) # test try: - RestClient(username="a", password="b").delete_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").delete_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except NotExistsError: pass @@ -926,8 +973,9 @@ class DatabaseUnitTest(unittest.TestCase): status_code=502) # test try: - RestClient(username="a", password="b").delete_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").delete_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ServiceConnectionError: pass @@ -939,8 +987,9 @@ class DatabaseUnitTest(unittest.TestCase): status_code=503) # test try: - RestClient(username="a", password="b").delete_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").delete_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ServiceError: pass @@ -952,8 +1001,9 @@ class DatabaseUnitTest(unittest.TestCase): status_code=200) # test try: - RestClient(username="a", password="b").delete_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient(username="a", password="b").delete_database_access( + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except ResponseCodeError: pass @@ -965,7 +1015,8 @@ class DatabaseUnitTest(unittest.TestCase): status_code=404) # test try: - RestClient().delete_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') + RestClient().delete_database_access(database_id="6bd39359-b154-456d-b9c2-caa516a45732", + user_id='abdbf897-e599-4e5a-a3f0-7529884ea011') except AuthenticationError: pass -- GitLab From 930aa3a0baf4f69632e16337a497df339593e356 Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Fri, 28 Feb 2025 10:12:07 +0100 Subject: [PATCH 03/11] WIP Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- .../target/create-event-listener.jar | Bin 10140 -> 10140 bytes dbrepo-data-service/pom.xml | 65 +++++- .../at/tuwien/endpoints/AccessEndpoint.java | 16 -- .../at/tuwien/endpoints/SubsetEndpoint.java | 15 +- .../at/tuwien/endpoints/ViewEndpoint.java | 5 +- .../tuwien/validation/EndpointValidator.java | 19 ++ .../src/main/resources/init/querystore.sql | 3 - .../endpoint/SubsetEndpointUnitTest.java | 59 +++-- .../endpoint/TableEndpointUnitTest.java | 65 ++++++ .../tuwien/endpoint/ViewEndpointUnitTest.java | 27 ++- .../tuwien/mvc/PrometheusEndpointMvcTest.java | 3 +- .../service/CredentialServiceUnitTest.java | 22 -- .../service/SubsetServiceIntegrationTest.java | 123 +++++++++- .../java/at/tuwien/config/GatewayConfig.java | 1 + .../java/at/tuwien/config/KeycloakConfig.java | 10 + .../gateway/impl/KeycloakGatewayImpl.java | 63 ++--- .../java/at/tuwien/mapper/MariaDbMapper.java | 216 +++++++++++++----- .../java/at/tuwien/mapper/MetadataMapper.java | 8 + .../at/tuwien/service/CredentialService.java | 7 - .../java/at/tuwien/service/SubsetService.java | 21 +- .../service/impl/CredentialServiceImpl.java | 6 - .../impl/DatabaseServiceMariaDbImpl.java | 4 +- .../impl/SubsetServiceMariaDbImpl.java | 23 +- dbrepo-metadata-db/1_setup-schema.sql | 20 +- .../at/tuwien/api/database/CreateViewDto.java | 2 +- .../tuwien/api/database/query/FilterDto.java | 8 +- .../api/database/query/FilterTypeDto.java | 28 +++ .../tuwien/api/database/query/OrderDto.java | 5 +- .../tuwien/api/database/query/SubsetDto.java | 2 +- dbrepo-metadata-service/pom.xml | 26 ++- .../at/tuwien/endpoints/DatabaseEndpoint.java | 4 +- .../src/test/resources/init/weather_at.sql | 12 +- .../java/at/tuwien/test/AbstractUnitTest.java | 12 +- .../main/java/at/tuwien/test/BaseTest.java | 125 ++++++++-- dbrepo-ui/assets/globals.css | 3 + dbrepo-ui/assets/globals.css.map | 2 +- dbrepo-ui/assets/globals.scss | 4 + dbrepo-ui/components/identifier/Summary.vue | 4 +- dbrepo-ui/components/subset/Builder.vue | 28 ++- dbrepo-ui/composables/query-service.ts | 7 +- dbrepo-ui/locales/en-US.json | 3 + .../[database_id]/subset/[subset_id]/info.vue | 3 +- .../[database_id]/view/[view_id]/info.vue | 3 +- helm/dbrepo/files/create-event-listener.jar | Bin 10140 -> 10140 bytes 44 files changed, 789 insertions(+), 293 deletions(-) delete mode 100644 dbrepo-data-service/rest-service/src/main/resources/init/querystore.sql create mode 100644 dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterTypeDto.java diff --git a/dbrepo-auth-service/listeners/target/create-event-listener.jar b/dbrepo-auth-service/listeners/target/create-event-listener.jar index cd7f74508b8bee100bac98aac20c40f44ddd150d..70fca91e2c62b6c899e74332a8e1398e9c8c4b75 100644 GIT binary patch delta 695 zcmbQ^KgVAvz?+#xgn@yBgF!zaCQ3p^J8PnlQoV2RVFiJ`>1zKQ?HN>-$<La7wYe;6 z?#gSw+03S8I$3S-e7k@8GO6Qzi{%<xYu{AwN#(pY<wfWI1)rB~wDfirayRE|4ETIg zG2Q#cg-zMZ&6YVIH!`$RN?W_qWd3X2`dbURt}iPr>G8=F30QGtK5ys@<5-J3rZQ2t z3i{U>bDf`9&-~pr{+CT=>Ej}^`KI?aKROV$;-+kX%-!p|xw5x>F~2YQMS7vc{|W!q zpI2=?akDMsd9mjA-+K*~ieGuh8^!3w;F;{rJ}+kViqaQPJ?Hf-PWYmtQ~V;~!S17n z8f5wGt%cUqe))5wagO6!^~H7n8A>bO9lG&t?S1|qogB7LB2U@ZZ}4CB%)EE&iWTRp zL!Ym2`=yvV!#r0pB>1$hT*%b}WgIRZURVFK_QhV1kvpgTm{WIG@I%qEXD-ocCwKTP zzpUfCZqkz=O^+`XC5D%7N~i~W2y9Z?>tt~^diSf-JMWu#6m@LklUwxr(j{)rCc7;x z%8y^jg5rUTfq{bo6c3X(GO94^1;k9g!Ke$SIhf?Yv?h}(vwlF#<Ul4ZFkQ!F0;abz zd4c7bn9qXgOU&IMdUFEH940X1KN~kEn87PBix;e=M{(BX<+6{M!5mGc$sDlwpL|5g z3M|N|Yy#3U*+SVCOjjuDf$5dXreOJp$`EyODlTAts!9}C{*X#An3hn@1=Ag>v0(az zsw0@zQ40gBf2k%td4Zbw<O_;iYysYkOd`ya7s^WUFhIeQMk~3=y-d=R?=y)_zN{t; J))S)c0RW)p5WoNc delta 719 zcmbQ^KgVAvz?+#xgn@yBgCS&fR8(%=kA{gtO7#be4k-xiO;`JWfS<uFS*m#Tw+mLc z&Skuvd*GIV+L1=zHTCg5W`1-1ZZmJ#&|llXU8nV8bb-hH16HxKdt7n^*o?WE9522! zRQA5ur1(8dY!|Dyn~t60vR*yWxvOPk-#h-wE>A4z`V!{dxKF6|YJ`(pNM2%m@Wlj2 z*&AWrJ6!9(-8sDOOYWr=x6)GV*3MP_IdP4{MEAzT4<T>8R~&e7zsCGReoM|D=YR9( z%)Y9m%=+kF>Ku7K_GR1q5{oY+%$VS#a6K)%)%mtZj*dm$wBv^lNYDL|suy+fv#rCr z)|dSItsbqdE&Ot&v8TgJwQzgA*wp%WPP3mazWx12%TKvWfiCs>H@2>MvBr!|rL0nY z^_$pabBpiA7oYfC6TN>haN5=zUl~7p>h0d|u<+}wzlSqd$~G}p>+NX@o1d9DL#=R? z+GGu>XF```*tF!1G0!~pu|g$;h3kpM%sKCKb1F;Une)o%GOXXzp0Ga3N-^$&Yqz-( zj~yc@9=I47I2b_jFnJ@R3Ul!4sL3}Nb-^?TlN^}VWKv}gSsgVwkVy+n*D;xZ>8(s& zV0k9yvtarXb2o_IoWL@N3C#G<#?1+4@CwZ0-RvUwh#9PJmFz4qt*JDb0~Y_2k0@Dz z1sRo1Kw2hSDBFVR3S~Voy;9i}EdNj$qE1f51<X%Xi2}<XQV9mr5~{gix<fS<OutZd z1k*ZdVUypg$xU9MX0Bh6n-k#8$RxsyNQ1lAJxFq5U|;}YTLuJJ(paxJnOEI(@;g~B Lel$&!L)1M0J#run diff --git a/dbrepo-data-service/pom.xml b/dbrepo-data-service/pom.xml index 697e9ece1b..35784c7d1f 100644 --- a/dbrepo-data-service/pom.xml +++ b/dbrepo-data-service/pom.xml @@ -8,6 +8,11 @@ <version>3.3.5</version> </parent> + <organization> + <name>TU Wien</name> + <url>https://www.tuwien.ac.at</url> + </organization> + <groupId>at.tuwien</groupId> <artifactId>dbrepo-data-service</artifactId> <name>dbrepo-data-service</name> @@ -54,14 +59,37 @@ <minio.version>8.5.7</minio.version> <guava.version>33.3.0-jre</guava.version> <spark.version>4.0.0-preview2</spark.version> + <keycloak.version>26.0.4</keycloak.version> <scala.version>2.13</scala.version> <antlr-runtime.version>3.5.2</antlr-runtime.version> <micrometer.version>1.10.0</micrometer.version> <!-- see https://github.com/apache/spark/blob/cde8e4a82e20a363861f451ebd5138efb3194ab8/pom.xml --> <hadoop.version>3.4.0</hadoop.version> <jakarta-servlet.version>5.0.0</jakarta-servlet.version> - <sonar.coverage.jacoco.xmlReportPaths>./report/target/site/jacoco-aggregate/jacoco.xml + <sonar.coverage.jacoco.xmlReportPaths> + ./report/target/site/jacoco-aggregate/jacoco.xml </sonar.coverage.jacoco.xmlReportPaths> + <CodeCacheSize>128m</CodeCacheSize> + <extraJavaTestArgs> + -XX:+IgnoreUnrecognizedVMOptions + --add-modules=jdk.incubator.vector + --add-opens=java.base/java.lang=ALL-UNNAMED + --add-opens=java.base/java.lang.invoke=ALL-UNNAMED + --add-opens=java.base/java.lang.reflect=ALL-UNNAMED + --add-opens=java.base/java.io=ALL-UNNAMED + --add-opens=java.base/java.net=ALL-UNNAMED + --add-opens=java.base/java.nio=ALL-UNNAMED + --add-opens=java.base/java.util=ALL-UNNAMED + --add-opens=java.base/java.util.concurrent=ALL-UNNAMED + --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED + --add-opens=java.base/jdk.internal.ref=ALL-UNNAMED + --add-opens=java.base/sun.nio.ch=ALL-UNNAMED + --add-opens=java.base/sun.nio.cs=ALL-UNNAMED + --add-opens=java.base/sun.security.action=ALL-UNNAMED + --add-opens=java.base/sun.util.calendar=ALL-UNNAMED + -Djdk.reflect.useDirectMethodHandle=false + -Dio.netty.tryReflectionSetAccessible=true + </extraJavaTestArgs> </properties> <dependencies> @@ -208,6 +236,22 @@ <artifactId>commons-validator</artifactId> <version>${commons-validator.version}</version> </dependency> + <dependency> + <groupId>org.jooq</groupId> + <artifactId>jooq</artifactId> + <version>${jooq.version}</version> + </dependency> + <!-- Authentication --> + <dependency> + <groupId>org.keycloak</groupId> + <artifactId>keycloak-common</artifactId> + <version>${keycloak.version}</version> + </dependency> + <dependency> + <groupId>org.keycloak</groupId> + <artifactId>keycloak-admin-client</artifactId> + <version>${keycloak.version}</version> + </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-hibernate6</artifactId> @@ -323,7 +367,26 @@ </execution> </executions> </plugin> + <!-- Surefire runs all Java tests --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <!-- Note config is repeated in scalatest config --> + <configuration> + <argLine>@{argLine} -ea -Xmx4g -Xss4m -XX:MaxMetaspaceSize=2g -XX:ReservedCodeCacheSize=${CodeCacheSize} + ${extraJavaTestArgs} + </argLine> + </configuration> + </plugin> </plugins> </build> + <licenses> + <license> + <name>Apache-2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.html</url> + <distribution>repo</distribution> + </license> + </licenses> + </project> diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java index 84d04971e3..5c93c4c021 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java @@ -153,22 +153,6 @@ public class AccessEndpoint extends RestEndpoint { } } - @PutMapping - @PreAuthorize("hasAuthority('system')") - @Operation(summary = "Invalidate access cache for database", - security = {@SecurityRequirement(name = "basicAuth")}, - hidden = true) - @ApiResponses(value = { - @ApiResponse(responseCode = "202", - description = "Invalidated access cache succeeded") - }) - public ResponseEntity<Void> invalidateAccess(@NotNull @PathVariable("databaseId") UUID databaseId) { - log.debug("endpoint empty access cache for database, databaseId={}", databaseId); - credentialService.invalidateAccess(databaseId); - return ResponseEntity.accepted() - .build(); - } - @DeleteMapping("/{userId}") @PreAuthorize("hasAuthority('system')") @Operation(summary = "Revoke access", diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java index 3a8109d92d..d3d461d257 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java @@ -1,11 +1,9 @@ package at.tuwien.endpoints; import at.tuwien.ExportResourceDto; -import at.tuwien.api.database.CreateViewDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.ViewColumnDto; import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.query.ExecuteStatementDto; import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.database.query.QueryPersistDto; import at.tuwien.api.database.query.SubsetDto; @@ -260,10 +258,11 @@ public class SubsetEndpoint extends RestEndpoint { QueryStoreInsertException, TableMalformedException, PaginationException, QueryNotSupportedException, NotAllowedException, UserNotFoundException, MetadataServiceException, TableNotFoundException, ViewMalformedException, ViewNotFoundException, ImageNotFoundException { - log.debug("endpoint create subset in database, databaseId={}, data={}, page={}, size={}, " + - "timestamp={}", databaseId, data, page, size, timestamp); + log.debug("endpoint create subset in database, databaseId={}, page={}, size={}, timestamp={}", databaseId, + page, size, timestamp); /* check */ endpointValidator.validateDataParams(page, size); + endpointValidator.validateFilterSubsetParams(data); /* parameters */ final UUID userId; if (principal != null) { @@ -287,8 +286,7 @@ public class SubsetEndpoint extends RestEndpoint { final DatabaseDto database = credentialService.getDatabase(databaseId); endpointValidator.validateOnlyPrivateSchemaAccess(database, principal); try { - final UUID subsetId = subsetService.create(database, mariaDbMapper.subsetDtoToRawQuery(database, data), - timestamp, userId); + final UUID subsetId = subsetService.create(database, data, timestamp, userId); return getData(databaseId, subsetId, principal, request, timestamp, page, size); } catch (SQLException e) { log.error("Failed to establish connection to database: {}", e.getMessage()); @@ -340,9 +338,8 @@ public class SubsetEndpoint extends RestEndpoint { @RequestParam(required = false) Long page, @RequestParam(required = false) Long size) throws PaginationException, DatabaseNotFoundException, RemoteUnavailableException, NotAllowedException, - QueryNotFoundException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - UserNotFoundException, MetadataServiceException, TableNotFoundException, ViewNotFoundException, - ViewMalformedException { + QueryNotFoundException, DatabaseUnavailableException, QueryMalformedException, UserNotFoundException, + MetadataServiceException, TableNotFoundException, ViewNotFoundException, ViewMalformedException { log.debug("endpoint get subset data, databaseId={}, subsetId={}, principal.name={} page={}, size={}", databaseId, subsetId, principal != null ? principal.getName() : null, page, size); endpointValidator.validateDataParams(page, size); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index fdf4f62f55..4c4748dc35 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -153,8 +153,11 @@ public class ViewEndpoint extends RestEndpoint { public ResponseEntity<ViewDto> create(@NotNull @PathVariable("databaseId") UUID databaseId, @Valid @RequestBody CreateViewDto data) throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, MetadataServiceException, - TableNotFoundException, ImageNotFoundException { + TableNotFoundException, ImageNotFoundException, QueryMalformedException { log.debug("endpoint create view, databaseId={}, data.name={}", databaseId, data.getName()); + /* check */ + endpointValidator.validateFilterSubsetParams(data.getQuery()); + /* create */ final DatabaseDto database = credentialService.getDatabase(databaseId); try { return ResponseEntity.status(HttpStatus.CREATED) diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java index 9ad13f5be6..5cbbe6bce0 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java @@ -3,6 +3,9 @@ package at.tuwien.validation; import at.tuwien.api.database.AccessTypeDto; import at.tuwien.api.database.DatabaseAccessDto; import at.tuwien.api.database.DatabaseDto; +import at.tuwien.api.database.query.FilterDto; +import at.tuwien.api.database.query.FilterTypeDto; +import at.tuwien.api.database.query.SubsetDto; import at.tuwien.config.QueryConfig; import at.tuwien.endpoints.RestEndpoint; import at.tuwien.exception.*; @@ -63,6 +66,22 @@ public class EndpointValidator extends RestEndpoint { validateOnlyAccess(database, principal, writeAccessOnly); } + public void validateFilterSubsetParams(SubsetDto subset) throws QueryMalformedException { + if (subset.getFilter() != null) { + final List<FilterDto> filters = subset.getFilter(); + FilterTypeDto previous = null; + for (int i = 0; i < filters.size(); i++) { + final FilterDto filter = filters.get(i); + if ((i == 0 && !filter.getType().equals(FilterTypeDto.WHERE)) || + (i > 0 && !previous.equals(FilterTypeDto.WHERE) && (filter.getType().equals(FilterTypeDto.AND) || filter.getType().equals(FilterTypeDto.OR)))) { + log.error("Failed to validate subset: invalid specification, must be where-[(and|or)-where]"); + throw new QueryMalformedException("Failed to validate subset: invalid specification, must be where-[(and|or)-where]"); + } + previous = filter.getType(); + } + } + } + public void validateOnlyPrivateSchemaHasRole(DatabaseDto database, Principal principal, String role) throws NotAllowedException { if (database.getIsSchemaPublic()) { diff --git a/dbrepo-data-service/rest-service/src/main/resources/init/querystore.sql b/dbrepo-data-service/rest-service/src/main/resources/init/querystore.sql deleted file mode 100644 index de488f89ee..0000000000 --- a/dbrepo-data-service/rest-service/src/main/resources/init/querystore.sql +++ /dev/null @@ -1,3 +0,0 @@ -CREATE PROCEDURE hash_table(IN name VARCHAR(255), OUT hash VARCHAR(255), OUT count BIGINT) BEGIN DECLARE _sql TEXT; SELECT CONCAT('SELECT SHA2(GROUP_CONCAT(CONCAT_WS(\'\',', GROUP_CONCAT(CONCAT('`', column_name, '`') ORDER BY column_name), ') SEPARATOR \',\'), 256) AS hash, COUNT(*) AS count FROM `', name, '` INTO @hash, @count;') FROM `information_schema`.`columns` WHERE `table_schema` = DATABASE() AND `table_name` = name INTO _sql; PREPARE stmt FROM _sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET hash = @hash; SET count = @count; END; -CREATE PROCEDURE store_query(IN query TEXT, IN executed DATETIME, OUT queryId BIGINT) BEGIN DECLARE _queryhash varchar(255) DEFAULT SHA2(query, 256); DECLARE _username varchar(255) DEFAULT REGEXP_REPLACE(current_user(), '@.*', ''); DECLARE _query TEXT DEFAULT CONCAT('CREATE OR REPLACE TABLE _tmp AS (', query, ')'); PREPARE stmt FROM _query; EXECUTE stmt; DEALLOCATE PREPARE stmt; CALL hash_table('_tmp', @hash, @count); DROP TABLE IF EXISTS `_tmp`; IF @hash IS NULL THEN INSERT INTO `qs_queries` (`created_by`, `query`, `query_normalized`, `is_persisted`, `query_hash`, `result_hash`, `result_number`, `executed`) SELECT _username, query, query, false, _queryhash, @hash, @count, executed WHERE NOT EXISTS (SELECT `id` FROM `qs_queries` WHERE `query_hash` = _queryhash AND `result_hash` IS NULL); SET queryId = (SELECT `id` FROM `qs_queries` WHERE `query_hash` = _queryhash AND `result_hash` IS NULL); ELSE INSERT INTO `qs_queries` (`created_by`, `query`, `query_normalized`, `is_persisted`, `query_hash`, `result_hash`, `result_number`, `executed`) SELECT _username, query, query, false, _queryhash, @hash, @count, executed WHERE NOT EXISTS (SELECT `id` FROM `qs_queries` WHERE `query_hash` = _queryhash AND `result_hash` = @hash); SET queryId = (SELECT `id` FROM `qs_queries` WHERE `query_hash` = _queryhash AND `result_hash` = @hash); END IF; END; -CREATE DEFINER = 'root' PROCEDURE _store_query(IN _username VARCHAR(255), IN query TEXT, IN executed DATETIME, OUT queryId BIGINT) BEGIN DECLARE _queryhash varchar(255) DEFAULT SHA2(query, 256); DECLARE _query TEXT DEFAULT CONCAT('CREATE OR REPLACE TABLE _tmp AS (', query, ')'); PREPARE stmt FROM _query; EXECUTE stmt; DEALLOCATE PREPARE stmt; CALL hash_table('_tmp', @hash, @count); DROP TABLE IF EXISTS `_tmp`; IF @hash IS NULL THEN INSERT INTO `qs_queries` (`created_by`, `query`, `query_normalized`, `is_persisted`, `query_hash`, `result_hash`, `result_number`, `executed`) SELECT _username, query, query, false, _queryhash, @hash, @count, executed WHERE NOT EXISTS (SELECT `id` FROM `qs_queries` WHERE `query_hash` = _queryhash AND `result_hash` IS NULL); SET queryId = (SELECT `id` FROM `qs_queries` WHERE `query_hash` = _queryhash AND `result_hash` IS NULL); ELSE INSERT INTO `qs_queries` (`created_by`, `query`, `query_normalized`, `is_persisted`, `query_hash`, `result_hash`, `result_number`, `executed`) SELECT _username, query, query, false, _queryhash, @hash, @count, executed WHERE NOT EXISTS (SELECT `id` FROM `qs_queries` WHERE `query_hash` = _queryhash AND `result_hash` = @hash); SET queryId = (SELECT `id` FROM `qs_queries` WHERE `query_hash` = _queryhash AND `result_hash` = @hash); END IF; END; \ No newline at end of file diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java index 0c44e3b459..a6a3802866 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java @@ -1,8 +1,9 @@ package at.tuwien.endpoint; -import at.tuwien.api.database.CreateViewDto; import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.query.*; +import at.tuwien.api.database.query.QueryDto; +import at.tuwien.api.database.query.QueryPersistDto; +import at.tuwien.api.database.query.SubsetDto; import at.tuwien.endpoints.SubsetEndpoint; import at.tuwien.exception.*; import at.tuwien.service.CredentialService; @@ -30,7 +31,6 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import java.security.Principal; import java.sql.SQLException; import java.time.Instant; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.UUID; @@ -162,6 +162,23 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { generic_findById(DATABASE_1_ID, QUERY_1_ID, "application/json", null, USER_1_PRINCIPAL); } + @Test + @WithMockUser(username = USER_1_USERNAME) + public void findById_privateDataPrivateSchemaAcceptEmpty_succeeds() throws DatabaseNotFoundException, SQLException, + RemoteUnavailableException, UserNotFoundException, QueryNotFoundException, MetadataServiceException, + DatabaseUnavailableException, TableNotFoundException, StorageUnavailableException, NotAllowedException, + QueryMalformedException, FormatNotAvailableException { + + /* mock */ + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); + when(subsetService.findById(DATABASE_1_PRIVILEGED_DTO, QUERY_1_ID)) + .thenReturn(QUERY_1_DTO); + + /* test */ + generic_findById(DATABASE_1_ID, QUERY_1_ID, null, null, USER_1_PRINCIPAL); + } + @Test @WithMockUser(username = USER_3_USERNAME) public void findById_publicDataPrivateSchema_succeeds() throws DatabaseNotFoundException, SQLException, @@ -305,9 +322,9 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(subsetService.getData(any(DatabaseDto.class), anyString())) .thenReturn(mock); - when(subsetService.findById(eq(DATABASE_3_PRIVILEGED_DTO), any(UUID.class))) + when(subsetService.findById(any(DatabaseDto.class), any(UUID.class))) .thenReturn(QUERY_5_DTO); - when(subsetService.create(eq(DATABASE_3_PRIVILEGED_DTO), eq(QUERY_5_STATEMENT), any(Instant.class), any(UUID.class))) + when(subsetService.create(any(DatabaseDto.class), any(SubsetDto.class), any(Instant.class), any(UUID.class))) .thenReturn(QUERY_5_ID); when(databaseService.inspectView(any(DatabaseDto.class), anyString())) .thenReturn(QUERY_5_VIEW_DTO); @@ -331,7 +348,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_3_ID)) .thenReturn(DATABASE_3_PRIVILEGED_DTO); - when(subsetService.create(any(DatabaseDto.class), eq(QUERY_5_STATEMENT), any(Instant.class), eq(USER_1_ID))) + when(subsetService.create(any(DatabaseDto.class), any(SubsetDto.class), any(Instant.class), eq(USER_1_ID))) .thenReturn(QUERY_5_ID); when(subsetService.findById(any(DatabaseDto.class), eq(QUERY_5_ID))) .thenReturn(QUERY_5_DTO); @@ -380,18 +397,18 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { when(credentialService.getDatabase(DATABASE_4_ID)) .thenReturn(DATABASE_4_PRIVILEGED_DTO); when(subsetService.findById(eq(DATABASE_4_PRIVILEGED_DTO), any(UUID.class))) - .thenReturn(QUERY_5_DTO); - when(subsetService.create(eq(DATABASE_4_PRIVILEGED_DTO), eq(QUERY_5_STATEMENT), any(Instant.class), eq(null))) - .thenReturn(QUERY_5_ID); + .thenReturn(QUERY_9_DTO); + when(subsetService.create(eq(DATABASE_4_PRIVILEGED_DTO), any(SubsetDto.class), any(Instant.class), eq(null))) + .thenReturn(QUERY_9_ID); when(subsetService.getData(any(DatabaseDto.class), anyString())) .thenReturn(mock); when(databaseService.inspectView(any(DatabaseDto.class), anyString())) - .thenReturn(QUERY_5_VIEW_DTO); + .thenReturn(QUERY_9_VIEW_DTO); when(httpServletRequest.getMethod()) .thenReturn("POST"); /* test */ - subsetEndpoint.create(DATABASE_4_ID, QUERY_5_SUBSET_DTO, null, httpServletRequest, null, null, null); + subsetEndpoint.create(DATABASE_4_ID, QUERY_9_SUBSET_DTO, null, httpServletRequest, null, null, null); } @Test @@ -407,9 +424,9 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - when(subsetService.findById(eq(DATABASE_1_PRIVILEGED_DTO), any(UUID.class))) + when(subsetService.findById(any(DatabaseDto.class), any(UUID.class))) .thenReturn(QUERY_1_DTO); - when(subsetService.create(eq(DATABASE_1_PRIVILEGED_DTO), eq(QUERY_1_STATEMENT), any(Instant.class), any(UUID.class))) + when(subsetService.create(any(DatabaseDto.class), any(SubsetDto.class), any(Instant.class), any(UUID.class))) .thenReturn(QUERY_1_ID); when(subsetService.getData(any(DatabaseDto.class), anyString())) .thenReturn(mock); @@ -433,7 +450,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { when(credentialService.getDatabase(DATABASE_2_ID)) .thenReturn(DATABASE_2_PRIVILEGED_DTO); when(subsetService.findById(eq(DATABASE_2_PRIVILEGED_DTO), any(UUID.class))) - .thenReturn(QUERY_2_DTO); + .thenReturn(QUERY_8_DTO); when(subsetService.getData(any(DatabaseDto.class), anyString())) .thenReturn(mock); when(httpServletRequest.getMethod()) @@ -441,7 +458,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - subsetEndpoint.create(DATABASE_2_ID, QUERY_5_SUBSET_DTO, null, httpServletRequest, null, null, null); + subsetEndpoint.create(DATABASE_2_ID, QUERY_8_SUBSET_DTO, null, httpServletRequest, null, null, null); }); } @@ -499,9 +516,9 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME) public void getData_private_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, - UserNotFoundException, DatabaseUnavailableException, NotAllowedException, TableMalformedException, - QueryMalformedException, QueryNotFoundException, PaginationException, SQLException, - MetadataServiceException, TableNotFoundException, ViewNotFoundException, ViewMalformedException { + UserNotFoundException, DatabaseUnavailableException, NotAllowedException, QueryMalformedException, + QueryNotFoundException, PaginationException, SQLException, MetadataServiceException, + TableNotFoundException, ViewNotFoundException, ViewMalformedException { final Dataset<Row> mock = sparkSession.emptyDataFrame(); /* mock */ @@ -560,9 +577,9 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME) public void getData_privateHead_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, - UserNotFoundException, DatabaseUnavailableException, NotAllowedException, TableMalformedException, - QueryMalformedException, QueryNotFoundException, PaginationException, SQLException, - MetadataServiceException, TableNotFoundException, ViewNotFoundException, ViewMalformedException { + UserNotFoundException, DatabaseUnavailableException, NotAllowedException, QueryMalformedException, + QueryNotFoundException, PaginationException, SQLException, MetadataServiceException, + TableNotFoundException, ViewNotFoundException, ViewMalformedException { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java index 57e6ede962..619ccf8cf7 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java @@ -789,6 +789,71 @@ public class TableEndpointUnitTest extends AbstractUnitTest { assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"system"}) + public void update_succeeds() throws DatabaseUnavailableException, TableNotFoundException, + TableMalformedException, RemoteUnavailableException, SQLException, MetadataServiceException { + + /* mock */ + when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_PRIVILEGED_DTO); + doNothing() + .when(tableService) + .updateTable(TABLE_8_PRIVILEGED_DTO, TABLE_8_UPDATE_DTO); + + /* test */ + final ResponseEntity<TableDto> response = tableEndpoint.update(DATABASE_3_ID, TABLE_8_ID, TABLE_8_UPDATE_DTO); + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"system"}) + public void update_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, + MetadataServiceException { + + /* mock */ + doThrow(TableNotFoundException.class) + .when(credentialService) + .getTable(DATABASE_3_ID, TABLE_8_ID); + + /* test */ + assertThrows(TableNotFoundException.class, () -> { + tableEndpoint.update(DATABASE_3_ID, TABLE_8_ID, TABLE_8_UPDATE_DTO); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"system"}) + public void update_unavailable_fails() throws TableNotFoundException, RemoteUnavailableException, + MetadataServiceException { + + /* mock */ + doThrow(RemoteUnavailableException.class) + .when(credentialService) + .getTable(DATABASE_3_ID, TABLE_8_ID); + + /* test */ + assertThrows(RemoteUnavailableException.class, () -> { + tableEndpoint.update(DATABASE_3_ID, TABLE_8_ID, TABLE_8_UPDATE_DTO); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"system"}) + public void update_exception_fails() throws TableNotFoundException, RemoteUnavailableException, + MetadataServiceException { + + /* mock */ + doThrow(MetadataServiceException.class) + .when(credentialService) + .getTable(DATABASE_3_ID, TABLE_8_ID); + + /* test */ + assertThrows(MetadataServiceException.class, () -> { + tableEndpoint.update(DATABASE_3_ID, TABLE_8_ID, TABLE_8_UPDATE_DTO); + }); + } + @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java index 82a9168e9f..3c38265a54 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java @@ -70,7 +70,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void create_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, SQLException, DatabaseUnavailableException, MetadataServiceException, TableNotFoundException, - ImageNotFoundException { + ImageNotFoundException, QueryMalformedException { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) @@ -298,6 +298,31 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { assertNotNull(response.getBody()); } + @Test + @WithAnonymousUser + public void getData_privateDataPrivateSchemaAnonymous_fails() throws RemoteUnavailableException, + ViewNotFoundException, QueryMalformedException, NotAllowedException, MetadataServiceException, + TableNotFoundException, DatabaseNotFoundException { + final Dataset<Row> mock = sparkSession.emptyDataFrame(); + + /* mock */ + when(credentialService.getView(DATABASE_1_ID, VIEW_1_ID)) + .thenReturn(VIEW_1_PRIVILEGED_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); + when(credentialService.getAccess(DATABASE_1_ID, USER_1_ID)) + .thenReturn(DATABASE_1_USER_1_READ_ACCESS_DTO); + when(subsetService.getData(any(DatabaseDto.class), anyString())) + .thenReturn(mock); + when(httpServletRequest.getMethod()) + .thenReturn("GET"); + + /* test */ + assertThrows(NotAllowedException.class, () -> { + viewEndpoint.getData(DATABASE_1_ID, VIEW_1_ID, null, null, null, httpServletRequest, null); + }); + } + @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"view-database-view-data"}) public void getData_privateHead_succeeds() throws RemoteUnavailableException, ViewNotFoundException, diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java index dacc80acce..ae03fdbf68 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java @@ -2,6 +2,7 @@ package at.tuwien.mvc; import at.tuwien.api.database.query.ExecuteStatementDto; import at.tuwien.api.database.query.ImportDto; +import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.database.query.QueryPersistDto; import at.tuwien.api.database.table.TupleDeleteDto; import at.tuwien.api.database.table.TupleDto; @@ -110,7 +111,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* ignore */ } try { - subsetEndpoint.create(DATABASE_1_ID, ExecuteStatementDto.builder().statement(QUERY_5_STATEMENT).build(), USER_1_PRINCIPAL, httpServletRequest, null, 0L, 10L); + subsetEndpoint.create(DATABASE_1_ID, QUERY_1_SUBSET_DTO, USER_1_PRINCIPAL, httpServletRequest, null, 0L, 10L); } catch (Exception e) { /* ignore */ } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/CredentialServiceUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/CredentialServiceUnitTest.java index 764dd92af3..a3e7f7ded7 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/CredentialServiceUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/CredentialServiceUnitTest.java @@ -344,26 +344,4 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { assertEquals(VIEW_1_ID, response.getId()); } - @Test - public void invalidateAccess_succeeds() throws NotAllowedException, RemoteUnavailableException, - MetadataServiceException { - - /* mock */ - when(metadataServiceGateway.getAccess(DATABASE_1_ID, USER_1_ID)) - .thenReturn(DATABASE_1_USER_1_READ_ACCESS_DTO) - .thenThrow(RuntimeException.class); - - /* pre-condition */ - final DatabaseAccessDto response = credentialService.getAccess(DATABASE_1_ID, USER_1_ID); - assertNotNull(response); - - /* test */ - credentialService.invalidateAccess(DATABASE_1_ID); - - /* post-condition */ - assertThrows(RuntimeException.class, () -> { - credentialService.getAccess(DATABASE_1_ID, USER_1_ID); - }); - } - } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java index cd92d5579c..6ec99aaa00 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java @@ -8,6 +8,8 @@ import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; +import org.apache.spark.sql.Dataset; +import org.apache.spark.sql.Row; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -20,6 +22,8 @@ import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import java.sql.SQLException; +import java.time.Instant; +import java.util.LinkedList; import java.util.List; import java.util.UUID; @@ -33,7 +37,7 @@ import static org.mockito.Mockito.when; public class SubsetServiceIntegrationTest extends AbstractUnitTest { @Autowired - private SubsetService queryService; + private SubsetService subsetService; @MockBean private MetadataServiceGateway metadataServiceGateway; @@ -112,7 +116,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { /* test */ persist_generic(queryId2, List.of(IDENTIFIER_5_BRIEF_DTO), true); - final QueryDto response = queryService.findById(DATABASE_1_PRIVILEGED_DTO, queryId2); + final QueryDto response = subsetService.findById(DATABASE_1_PRIVILEGED_DTO, queryId2); assertEquals(queryId2, response.getId()); assertTrue(response.getIsPersisted()); } @@ -129,11 +133,118 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { /* test */ persist_generic(queryId1, List.of(IDENTIFIER_2_BRIEF_DTO), false); - final QueryDto response = queryService.findById(DATABASE_1_PRIVILEGED_DTO, queryId1); + final QueryDto response = subsetService.findById(DATABASE_1_PRIVILEGED_DTO, queryId1); assertEquals(queryId1, response.getId()); assertFalse(response.getIsPersisted()); } + @Test + public void create_illegalQuery_fails() { + + /* test */ + assertThrows(QueryStoreInsertException.class, () -> { + subsetService.create(DATABASE_1_PRIVILEGED_DTO, QUERY_1_SUBSET_DTO, QUERY_1_CREATED, USER_1_ID); + }); + } + + @Test + public void getData_succeeds() throws QueryMalformedException, TableNotFoundException { + final List<List<String>> expected = List.of( + List.of("1", "2008-12-01", "Albury", "13.4", "0.6"), + List.of("2", "2008-12-02", "Albury", "7.4", "0.0"), + List.of("3", "2008-12-03", "Albury", "12.9", "0.0")); + + + /* test */ + final Dataset<Row> response = subsetService.getData(DATABASE_1_PRIVILEGED_DTO, QUERY_1_STATEMENT); + assertNotNull(response); + final List<List<String>> mapped = response.collectAsList() + .stream() + .map(row -> { + final List<String> map = new LinkedList<>(); + for (int i = 0; i < response.columns().length; i++) { + map.add(row.get(i) != null ? String.valueOf(row.get(i)) : ""); + } + return map; + }) + .toList(); + assertEquals(expected, mapped); + } + + @Test + public void getData_notFound_fails() { + + /* test */ + assertThrows(TableNotFoundException.class, () -> { + subsetService.getData(DATABASE_1_PRIVILEGED_DTO, "SELECT 1 FROM i_do_not_exist"); + }); + } + + @Test + public void reExecuteCount_succeeds() throws SQLException, QueryMalformedException { + + /* test */ + final Long response = subsetService.reExecuteCount(DATABASE_1_PRIVILEGED_DTO, QUERY_1_DTO); + assertNotNull(response); + } + + @Test + public void reExecuteCount_malformed_fails() { + final QueryDto request = QueryDto.builder() + .execution(Instant.now()) + .databaseId(DATABASE_1_ID) + .query("SELECT") // <<< + .build(); + + /* test */ + assertThrows(QueryMalformedException.class, () -> { + subsetService.reExecuteCount(DATABASE_1_PRIVILEGED_DTO, request); + }); + } + + @Test + public void executeCountNonPersistent_succeeds() throws SQLException, QueryMalformedException { + + /* test */ + final Long response = subsetService.executeCountNonPersistent(DATABASE_1_PRIVILEGED_DTO, QUERY_1_STATEMENT, QUERY_1_CREATED); + assertNotNull(response); + } + + @Test + public void executeCountNonPersistent_malformed_fails() { + + /* test */ + assertThrows(QueryMalformedException.class, () -> { + subsetService.executeCountNonPersistent(DATABASE_1_PRIVILEGED_DTO, "SELECT", QUERY_1_CREATED); + }); + } + + @Test + public void executeCountNonPersistent_illegalQuery_fails() { + + /* test */ + assertThrows(QueryMalformedException.class, () -> { + subsetService.executeCountNonPersistent(DATABASE_1_PRIVILEGED_DTO, "DROP DATABASE `weather`", QUERY_1_CREATED); + }); + } + + @Test + public void storeQuery_succeeds() throws SQLException, QueryStoreInsertException, ViewMalformedException { + + /* test */ + final UUID response = subsetService.storeQuery(DATABASE_1_PRIVILEGED_DTO, QUERY_1_STATEMENT, QUERY_1_CREATED, USER_1_ID); + assertNotNull(response); + } + + @Test + public void storeQuery_fails() { + + /* test */ + assertThrows(QueryStoreInsertException.class, () -> { + subsetService.storeQuery(DATABASE_1_PRIVILEGED_DTO, "DROP DATABASE `weather`", QUERY_1_CREATED, USER_1_ID); + }); + } + protected void findById_generic(UUID queryId) throws RemoteUnavailableException, SQLException, UserNotFoundException, QueryNotFoundException, MetadataServiceException, DatabaseNotFoundException, InterruptedException { @@ -148,7 +259,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { .thenReturn(USER_1_DTO); /* test */ - final QueryDto response = queryService.findById(DATABASE_1_PRIVILEGED_DTO, queryId); + final QueryDto response = subsetService.findById(DATABASE_1_PRIVILEGED_DTO, queryId); assertEquals(queryId, response.getId()); } @@ -166,7 +277,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { .thenReturn(List.of(IDENTIFIER_2_BRIEF_DTO, IDENTIFIER_5_BRIEF_DTO)); /* test */ - return queryService.findAll(DATABASE_1_PRIVILEGED_DTO, filterPersisted); + return subsetService.findAll(DATABASE_1_PRIVILEGED_DTO, filterPersisted); } protected void persist_generic(UUID queryId, List<IdentifierBriefDto> identifiers, Boolean persist) @@ -181,7 +292,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { .thenReturn(identifiers); /* test */ - queryService.persist(DATABASE_1_PRIVILEGED_DTO, queryId, persist); + subsetService.persist(DATABASE_1_PRIVILEGED_DTO, queryId, persist); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java index c511f2b511..1a92faf86f 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/config/GatewayConfig.java @@ -5,6 +5,7 @@ import at.tuwien.gateway.KeycloakGateway; import lombok.Getter; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java b/dbrepo-data-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java index cc6960ba39..57183b8767 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/config/KeycloakConfig.java @@ -1,8 +1,11 @@ package at.tuwien.config; import lombok.Getter; +import org.keycloak.admin.client.Keycloak; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; @Getter @Configuration @@ -22,4 +25,11 @@ public class KeycloakConfig { @Value("${dbrepo.keycloak.clientSecret}") private String keycloakClientSecret; + + private final String realm = "dbrepo"; + + @Bean + public Keycloak keycloak() { + return Keycloak.getInstance(keycloakEndpoint, "master", keycloakUsername, keycloakPassword, "admin-cli"); + } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java index 1e235de4c6..62a101c5ce 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java @@ -2,67 +2,42 @@ package at.tuwien.gateway.impl; import at.tuwien.api.keycloak.TokenDto; import at.tuwien.config.KeycloakConfig; -import at.tuwien.exception.AccountNotSetupException; -import at.tuwien.exception.AuthServiceConnectionException; -import at.tuwien.exception.CredentialsInvalidException; import at.tuwien.gateway.KeycloakGateway; +import at.tuwien.mapper.MetadataMapper; import lombok.extern.log4j.Log4j2; +import org.keycloak.OAuth2Constants; +import org.keycloak.admin.client.Keycloak; +import org.keycloak.admin.client.KeycloakBuilder; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.*; import org.springframework.stereotype.Service; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.RestTemplate; @Log4j2 @Service public class KeycloakGatewayImpl implements KeycloakGateway { private final KeycloakConfig keycloakConfig; + private final MetadataMapper metadataMapper; @Autowired - public KeycloakGatewayImpl(KeycloakConfig keycloakConfig) { + public KeycloakGatewayImpl(KeycloakConfig keycloakConfig, MetadataMapper metadataMapper) { this.keycloakConfig = keycloakConfig; + this.metadataMapper = metadataMapper; } @Override - public TokenDto obtainUserToken(String username, String password) throws AuthServiceConnectionException, - CredentialsInvalidException, AccountNotSetupException { - final HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - final MultiValueMap<String, String> payload = new LinkedMultiValueMap<>(); - payload.add("username", username); - payload.add("password", password); - payload.add("grant_type", "password"); - payload.add("scope", "openid roles"); - payload.add("client_id", keycloakConfig.getKeycloakClient()); - payload.add("client_secret", keycloakConfig.getKeycloakClientSecret()); - final String url = keycloakConfig.getKeycloakEndpoint() + "/realms/dbrepo/protocol/openid-connect/token"; - log.trace("request user token from url: {}", url); - final ResponseEntity<TokenDto> response; - try { - response = new RestTemplate() - .exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class); - } catch (HttpServerErrorException e) { - log.error("Failed to obtain user token: {}", e.getMessage()); - throw new AuthServiceConnectionException("Failed to obtain user token: " + e.getMessage(), e); - } catch (HttpClientErrorException.BadRequest e) { - if (e.getResponseBodyAsByteArray() != null && e.getResponseBodyAsByteArray().length > 0) { - final String error = e.getResponseBodyAsString(); - if (error != null && error.contains("invalid_grant")) { - log.error("Failed to obtain user token: {}", error); - throw new AccountNotSetupException("Failed to obtain user token: " + error, e); - } - } - log.error("Failed to obtain user token: bad request"); - throw new CredentialsInvalidException("Bad request", e); - } catch (HttpClientErrorException.Unauthorized e) { - log.error("Failed to obtain user token: invalid credentials"); - throw new CredentialsInvalidException("Invalid credentials: " + e.getMessage(), e); + public TokenDto obtainUserToken(String username, String password) { + try (Keycloak userKeycloak = KeycloakBuilder.builder() + .serverUrl(keycloakConfig.getKeycloakEndpoint()) + .realm(keycloakConfig.getRealm()) + .grantType(OAuth2Constants.PASSWORD) + .clientId(keycloakConfig.getKeycloakClient()) + .clientSecret(keycloakConfig.getKeycloakClientSecret()) + .username(username) + .password(password) + .build()) { + return metadataMapper.accessTokenResponseToTokenDto(userKeycloak.tokenManager() + .getAccessToken()); } - return response.getBody(); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java index 226d8fb3c9..d7250ccc74 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java @@ -3,8 +3,13 @@ package at.tuwien.mapper; import at.tuwien.api.container.image.OperatorDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.query.FilterDto; +import at.tuwien.api.database.query.FilterTypeDto; +import at.tuwien.api.database.query.OrderDto; import at.tuwien.api.database.query.SubsetDto; -import at.tuwien.api.database.table.*; +import at.tuwien.api.database.table.TableDto; +import at.tuwien.api.database.table.TupleDeleteDto; +import at.tuwien.api.database.table.TupleDto; +import at.tuwien.api.database.table.TupleUpdateDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.columns.CreateTableColumnDto; @@ -13,6 +18,10 @@ import at.tuwien.exception.QueryMalformedException; import at.tuwien.exception.TableMalformedException; import at.tuwien.exception.TableNotFoundException; import at.tuwien.utils.MariaDbUtil; +import org.jooq.Record; +import org.jooq.*; +import org.jooq.conf.ParamType; +import org.jooq.conf.StatementType; import org.mapstruct.Mapper; import org.mapstruct.Named; @@ -30,6 +39,9 @@ import java.util.*; import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.jooq.impl.DSL.field; +import static org.jooq.impl.DSL.select; + @Mapper(componentModel = "spring", uses = {MetadataMapper.class, DataMapper.class}) public interface MariaDbMapper { @@ -791,79 +803,157 @@ public interface MariaDbMapper { return statement.toString(); } + default SelectConditionStep<Record> subsetDtoToSelectConditions(SelectJoinStep<Record> step, DatabaseDto database, + SubsetDto data) throws TableNotFoundException, + ImageNotFoundException { + if (data == null || data.getFilter().isEmpty()) { + return step.where(); + } + SelectConditionStep<Record> conditions = step.where(); + FilterTypeDto next = null; + for (int i = 0; i < data.getFilter().size(); i++) { + final FilterDto filter = data.getFilter().get(i); + final ColumnDto column = columnIdToColumnDto(database, filter.getColumnId()); + if (i == 0) { + conditions = step.where(filterDtoToCondition(database, column, filter)); + } else if (next != null) { + if (next.equals(FilterTypeDto.OR)) { + conditions = conditions.or(filterDtoToCondition(database, column, filter)); + } else if (next.equals(FilterTypeDto.AND)) { + conditions = conditions.and(filterDtoToCondition(database, column, filter)); + } + } + next = filter.getType(); + } + return conditions; + } + + default Condition filterDtoToCondition(DatabaseDto database, ColumnDto column, FilterDto data) + throws ImageNotFoundException { + final String operator = operatorIdToOperatorDto(database, data.getOperatorId()).getValue(); + switch (operator) { + case "=": + case "<=>": + return field(column.getInternalName()).eq(data.getValue()); + case "<": + return field(column.getInternalName()).lt(data.getValue()); + case "<=": + return field(column.getInternalName()).le(data.getValue()); + case ">": + return field(column.getInternalName()).gt(data.getValue()); + case ">=": + return field(column.getInternalName()).ge(data.getValue()); + case "!=": + return field(column.getInternalName()).ne(data.getValue()); + case "LIKE": + return field(column.getInternalName()).like(data.getValue()); + case "NOT LIKE": + return field(column.getInternalName()).notLike(data.getValue()); + case "IN": + return field(column.getInternalName()).in(data.getValue()); + case "NOT IN": + return field(column.getInternalName()).notIn(data.getValue()); + case "IS NOT NULL": + return field(column.getInternalName()).isNotNull(); + case "IS NULL": + return field(column.getInternalName()).isNull(); + case "REGEXP": + return field(column.getInternalName()).likeRegex(data.getValue()); + case "NOT REGEXP": + return field(column.getInternalName()).notLikeRegex(data.getValue()); + } + log.error("Failed to map operator: {}", operator); + throw new IllegalArgumentException("Failed to map operator: " + operator); + } + + default SelectSeekStepN<Record> subsetDtoToSelectOrder(SelectConditionStep<Record> step, DatabaseDto database, + SubsetDto data) throws TableNotFoundException { + final List<OrderField<Object>> sort = new LinkedList<>(); + for (OrderDto order : data.getOrder()) { + final ColumnDto column = columnIdToColumnDto(database, order.getColumn()); + switch (order.getDirection()) { + case ASC -> sort.add(field(column.getInternalName()).asc()); + case DESC -> sort.add(field(column.getInternalName()).desc()); + } + sort.add(field(column.getInternalName())); + } + return step.orderBy(sort); + } + default String subsetDtoToRawQuery(DatabaseDto database, SubsetDto data) throws TableNotFoundException, ImageNotFoundException { - final StringBuilder builder = new StringBuilder("SELECT "); - final Optional<TableDto> optional = database.getTables() + final TableDto table = tableIdToTableDto(database, data.getTableId()); + final List<Field<Object>> columns = table.getColumns() .stream() - .filter(t -> t.getId().equals(data.getTableId())) + .filter(c -> data.getColumns().contains(c.getId())) + .map(c -> field(c.getInternalName())) + .toList(); + final SelectJoinStep<Record> query = select(columns) + .from(table.getInternalName()); + final SelectConditionStep<Record> where = subsetDtoToSelectConditions(query, database, data); + final String sql; + if (data.getOrder() == null) { + sql = where.getSQL(ParamType.INLINED); + } else { + sql = subsetDtoToSelectOrder(where, database, data) + .getSQL(ParamType.INLINED); + } + log.trace("mapped prepared query: {}", sql); + return sql; + } + + default ColumnDto columnIdToColumnDto(TableDto table, UUID columnId) throws TableNotFoundException { + final Optional<ColumnDto> optional = table.getColumns() + .stream() + .filter(c -> c.getId().equals(columnId)) .findFirst(); if (optional.isEmpty()) { - log.error("Failed to find table with id: {}", data.getTableId()); - throw new TableNotFoundException("Failed to find table"); + log.error("Failed to find filtered column with id: {}", columnId); + throw new TableNotFoundException("Failed to find filtered column"); } - final List<ColumnDto> columns = optional.get() - .getColumns() + return optional.get(); + } + + default ColumnDto columnIdToColumnDto(DatabaseDto database, UUID columnId) throws TableNotFoundException { + if (columnId == null) { + return null; + } + final Optional<ColumnDto> optional = database.getTables() .stream() - .filter(c -> data.getColumns().contains(c.getId())) - .toList(); - if (data.getColumns().size() != columns.size()) { - log.error("Failed to find all requested columns"); - throw new TableNotFoundException("Failed to find all requested columns"); + .map(TableDto::getColumns) + .flatMap(List::stream) + .filter(column -> column.getId().equals(columnId)) + .findFirst(); + if (optional.isEmpty()) { + log.error("Failed to find column: {}", columnId); + throw new TableNotFoundException("Failed to find column"); } - builder.append(String.join(", ", columns.stream().map(column -> "`" + column.getInternalName() + "`").toList())); - builder.append("FROM `") - .append(optional.get().getInternalName()) - .append("`"); - if (data.getFilter() != null) { - builder.append(" WHERE "); - for (FilterDto filter : data.getFilter()) { - final Optional<ColumnDto> optional1 = optional.get() - .getColumns() - .stream() - .filter(c -> c.getId().equals(filter.getColumnId())) - .findFirst(); - if (optional1.isEmpty()) { - log.error("Failed to find filtered column with id: {}", filter.getColumnId()); - throw new TableNotFoundException("Failed to find filtered column"); - } - final ColumnDto column = optional1.get(); - final Optional<OperatorDto> optional2 = database.getContainer() - .getImage() - .getOperators() - .stream() - .filter(op -> op.getId().equals(filter.getOperatorId())) - .findFirst(); - if (optional2.isEmpty()) { - log.error("Failed to find operator with id: {}", filter.getOperatorId()); - throw new ImageNotFoundException("Failed to find operator"); - } - builder.append("`") - .append(column.getInternalName()) - .append("` ") - .append(optional2.get() - .getValue()) - .append(" ") - .append(tableColumnTypeQuote(column.getColumnType(), filter.getValue())); - if (filter.getIsAnd() != null) { - if (filter.getIsAnd()) { - builder.append(" AND "); - } else { - builder.append(" OR "); - } - } - } + return optional.get(); + } + + default OperatorDto operatorIdToOperatorDto(DatabaseDto database, UUID operatorId) throws ImageNotFoundException { + final Optional<OperatorDto> optional = database.getContainer() + .getImage() + .getOperators() + .stream() + .filter(op -> op.getId().equals(operatorId)) + .findFirst(); + if (optional.isEmpty()) { + log.error("Failed to find operator with id: {}", operatorId); + throw new ImageNotFoundException("Failed to find operator"); } - log.trace("mapped raw query: {}", builder); - return builder.toString(); + return optional.get(); } - default String tableColumnTypeQuote(ColumnTypeDto data, String value) { - if (List.of(ColumnTypeDto.CHAR, ColumnTypeDto.VARCHAR, ColumnTypeDto.TINYTEXT, ColumnTypeDto.TEXT, - ColumnTypeDto.MEDIUMTEXT, ColumnTypeDto.LONGTEXT, ColumnTypeDto.DATE, ColumnTypeDto.DATETIME, - ColumnTypeDto.TIMESTAMP).contains(data)) { - return "'" + value + "'"; + default TableDto tableIdToTableDto(DatabaseDto database, UUID tableId) throws TableNotFoundException { + final Optional<TableDto> optional = database.getTables() + .stream() + .filter(t -> t.getId().equals(tableId)) + .findFirst(); + if (optional.isEmpty()) { + log.error("Failed to find table with id: {}", tableId); + throw new TableNotFoundException("Failed to find table"); } - return value; + return optional.get(); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java index 803116e602..8c9aed92d3 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -7,13 +7,16 @@ import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.ViewColumnDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.query.QueryDto; +import at.tuwien.api.database.query.SubsetDto; import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.identifier.IdentifierBriefDto; import at.tuwien.api.identifier.IdentifierDto; +import at.tuwien.api.keycloak.TokenDto; import at.tuwien.api.user.UserBriefDto; import at.tuwien.api.user.UserDto; +import org.keycloak.representations.AccessTokenResponse; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; @@ -45,6 +48,11 @@ public interface MetadataMapper { UserDto userDtoToUserDto(UserDto data); + @Mappings({ + @Mapping(target = "accessToken", source = "token") + }) + TokenDto accessTokenResponseToTokenDto(AccessTokenResponse data); + UserBriefDto userDtoToUserBriefDto(UserDto data); @Mappings({ diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/CredentialService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/CredentialService.java index 543e84ab51..c52455a29b 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/CredentialService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/CredentialService.java @@ -92,11 +92,4 @@ public interface CredentialService { */ DatabaseAccessDto getAccess(UUID databaseId, UUID userId) throws RemoteUnavailableException, MetadataServiceException, NotAllowedException; - - /** - * Invalidate the caches to force a refresh of access to a database with given id. - * - * @param databaseId The database id. - */ - void invalidateAccess(UUID databaseId); } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java index 49bd560c7a..30d4baca5c 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/SubsetService.java @@ -2,6 +2,7 @@ package at.tuwien.service; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.query.QueryDto; +import at.tuwien.api.database.query.SubsetDto; import at.tuwien.exception.*; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; @@ -17,15 +18,15 @@ public interface SubsetService { * Creates a subset from the given statement at given time in the given database. * * @param database The database. - * @param statement The subset statement. + * @param subset The subset information. * @param timestamp The timestamp as of which the data is queried. If smaller than <now>, historic data is queried. * @param userId The user id of the creating user. * @return The query id. * @throws QueryStoreInsertException The query store refused to insert the query. * @throws SQLException The connection to the database could not be established. */ - UUID create(DatabaseDto database, String statement, Instant timestamp, UUID userId) - throws QueryStoreInsertException, SQLException; + UUID create(DatabaseDto database, SubsetDto subset, Instant timestamp, UUID userId) + throws QueryStoreInsertException, SQLException, QueryMalformedException, TableNotFoundException, ImageNotFoundException, ViewMalformedException; /** * Counts the subset row count of a query of a given subset in the given database. @@ -33,11 +34,10 @@ public interface SubsetService { * @param database The database. * @param query The subset. * @return The row count. - * @throws TableMalformedException The table is malformed. + * @throws QueryMalformedException The query is malformed. * @throws SQLException The connection to the database could not be established. */ - Long reExecuteCount(DatabaseDto database, QueryDto query) throws TableMalformedException, - SQLException, QueryMalformedException; + Long reExecuteCount(DatabaseDto database, QueryDto query) throws SQLException, QueryMalformedException; /** * Retrieve data from a subset in a database and optionally paginate with number of page and size of results. @@ -74,10 +74,9 @@ public interface SubsetService { * @return The row count. * @throws SQLException The connection to the database could not be established. * @throws QueryMalformedException The mapped query produced a database error. - * @throws TableMalformedException The database table is malformed. */ Long executeCountNonPersistent(DatabaseDto database, String statement, Instant timestamp) - throws SQLException, QueryMalformedException, TableMalformedException; + throws SQLException, QueryMalformedException; /** * Finds a query in the query store of the given database id and query id. @@ -99,14 +98,14 @@ public interface SubsetService { * Inserts a query and metadata to the query store of a given database id. * * @param database The database. - * @param query The query statement. + * @param statement The query statement. * @param userId The user id. * @return The stored query id on success. * @throws SQLException The connection to the database could not be established. * @throws QueryStoreInsertException The query store failed to insert the query. */ - UUID storeQuery(DatabaseDto database, String query, Instant timestamp, UUID userId) throws SQLException, - QueryStoreInsertException; + UUID storeQuery(DatabaseDto database, String statement, Instant timestamp, UUID userId) throws SQLException, + QueryStoreInsertException, ViewMalformedException; /** * Persists a query to be displayed in the frontend. diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CredentialServiceImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CredentialServiceImpl.java index 8f3553515f..79a33866c3 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CredentialServiceImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CredentialServiceImpl.java @@ -70,12 +70,6 @@ public class CredentialServiceImpl implements CredentialService { return table; } - @Override - public void invalidateAccess(UUID databaseId) { - accessCache.invalidate(databaseId); - log.debug("invalidated access for database with id {} in cache", databaseId); - } - @Override public ContainerDto getContainer(UUID id) throws RemoteUnavailableException, MetadataServiceException, ContainerNotFoundException { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java index 136a8d740c..b859bcb89e 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java @@ -1,6 +1,5 @@ package at.tuwien.service.impl; -import at.tuwien.api.database.CreateViewDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.table.TableDto; @@ -113,8 +112,7 @@ public class DatabaseServiceMariaDbImpl extends DataConnector implements Databas dataSource.close(); } log.info("Created table with name {}", tableName); - final TableDto table = inspectTable(database, tableName); - return table; + return inspectTable(database, tableName); } @Override diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java index 8adaae9c6a..869f12bde2 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java @@ -2,6 +2,7 @@ package at.tuwien.service.impl; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.query.QueryDto; +import at.tuwien.api.database.query.SubsetDto; import at.tuwien.api.identifier.IdentifierBriefDto; import at.tuwien.api.identifier.IdentifierTypeDto; import at.tuwien.exception.*; @@ -53,11 +54,10 @@ public class SubsetServiceMariaDbImpl extends DataConnector implements SubsetSer .option("query", query) .load(); } catch (Exception e) { - if (e instanceof ExtendedAnalysisException exception) { - if (exception.getSimpleMessage().contains("TABLE_OR_VIEW_NOT_FOUND")) { - log.error("Failed to find named reference: {}", exception.getSimpleMessage()); - throw new TableNotFoundException("Failed to find named reference: " + exception.getSimpleMessage()) /* remove throwable on purpose, clutters the output */; - } + if (e instanceof ExtendedAnalysisException && e.getMessage().contains("TABLE_OR_VIEW_NOT_FOUND") + || e instanceof SQLSyntaxErrorException && e.getMessage().contains("doesn't exist")) { + log.error("Failed to find named reference: {}", e.getMessage()); + throw new TableNotFoundException("Failed to find named reference: " + e.getMessage()) /* remove throwable on purpose, clutters the output */; } log.error("Malformed query: {}", e.getMessage()); throw new QueryMalformedException("Malformed query: " + e.getMessage(), e); @@ -65,14 +65,15 @@ public class SubsetServiceMariaDbImpl extends DataConnector implements SubsetSer } @Override - public UUID create(DatabaseDto database, String statement, Instant timestamp, UUID userId) - throws QueryStoreInsertException, SQLException { + public UUID create(DatabaseDto database, SubsetDto subset, Instant timestamp, UUID userId) + throws QueryStoreInsertException, SQLException, QueryMalformedException, TableNotFoundException, + ImageNotFoundException, ViewMalformedException { + final String statement = mariaDbMapper.subsetDtoToRawQuery(database, subset); return storeQuery(database, statement, timestamp, userId); } @Override - public Long reExecuteCount(DatabaseDto database, QueryDto query) throws TableMalformedException, - SQLException, QueryMalformedException { + public Long reExecuteCount(DatabaseDto database, QueryDto query) throws SQLException, QueryMalformedException { return executeCountNonPersistent(database, query.getQuery(), query.getExecution()); } @@ -112,7 +113,7 @@ public class SubsetServiceMariaDbImpl extends DataConnector implements SubsetSer @Override public Long executeCountNonPersistent(DatabaseDto database, String statement, Instant timestamp) - throws SQLException, QueryMalformedException, TableMalformedException { + throws SQLException, QueryMalformedException { final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); try { @@ -123,7 +124,7 @@ public class SubsetServiceMariaDbImpl extends DataConnector implements SubsetSer return mariaDbMapper.resultSetToNumber(resultSet); } catch (SQLException e) { log.error("Failed to map object: {}", e.getMessage()); - throw new TableMalformedException("Failed to map object: " + e.getMessage(), e); + throw new QueryMalformedException("Failed to map object: " + e.getMessage(), e); } finally { dataSource.close(); } diff --git a/dbrepo-metadata-db/1_setup-schema.sql b/dbrepo-metadata-db/1_setup-schema.sql index 17d303ea7d..2ca58927da 100644 --- a/dbrepo-metadata-db/1_setup-schema.sql +++ b/dbrepo-metadata-db/1_setup-schema.sql @@ -596,32 +596,14 @@ VALUES ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Equal operator', '=', ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Greater than or equal operator', '>=', 'https://mariadb.com/kb/en/greater-than-or-equal/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Not equal operator', '!=', 'https://mariadb.com/kb/en/not-equal/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Addition operator', '+', - 'https://mariadb.com/kb/en/addition-operator/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Division operator', '/', - 'https://mariadb.com/kb/en/division-operator/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Modulo operator', '%', 'https://mariadb.com/kb/en/modulo-operator/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Multiplication operator', '*', - 'https://mariadb.com/kb/en/multiplication-operator/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Subtraction operator', '-', - 'https://mariadb.com/kb/en/subtraction-operator-/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'LIKE', 'LIKE', 'https://mariadb.com/kb/en/like/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'NOT LIKE', 'NOT LIKE', 'https://mariadb.com/kb/en/not-like/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'IN', 'IN', 'https://mariadb.com/kb/en/in/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'NOT IN', 'NOT IN', 'https://mariadb.com/kb/en/not-in/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'IS', 'IS', 'https://mariadb.com/kb/en/is/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'IS NOT', 'IS NOT', 'https://mariadb.com/kb/en/is-not/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'IS NOT NULL', 'IS NOT NULL', 'https://mariadb.com/kb/en/is-not-null/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'IS NULL', 'IS NULL', 'https://mariadb.com/kb/en/is-null/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'ISNULL', 'ISNULL', 'https://mariadb.com/kb/en/isnull/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'REGEXP', 'REGEXP', 'https://mariadb.com/kb/en/regexp/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'NOT REGEXP', 'NOT REGEXP', 'https://mariadb.com/kb/en/not-regexp/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Bitwise AND', '&', 'https://mariadb.com/kb/en/bitwise_and/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Bitwise OR', '|', 'https://mariadb.com/kb/en/bitwise-or/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Bitwise XOR', '^', 'https://mariadb.com/kb/en/bitwise-xor/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Bitwise NOT', '~', 'https://mariadb.com/kb/en/bitwise-not/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Left shift', '<<', 'https://mariadb.com/kb/en/shift-left/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Right shift', '>>', 'https://mariadb.com/kb/en/shift-right/'); + ('d79cb089-363c-488b-9717-649e44d8fcc5', 'NOT REGEXP', 'NOT REGEXP', 'https://mariadb.com/kb/en/not-regexp/'); INSERT INTO `mdb_ontologies` (prefix, uri, uri_pattern, sparql_endpoint, rdf_path) diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateViewDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateViewDto.java index f2c188c7e5..9a9558470f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateViewDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/CreateViewDto.java @@ -24,7 +24,7 @@ public class CreateViewDto { @Schema(example = "Air Quality") private String name; - @NotBlank + @NotNull private SubsetDto query; @NotNull diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java index bcb4a338a2..e78cf6ecb4 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java @@ -19,21 +19,17 @@ import java.util.UUID; public class FilterDto { @NotNull + private FilterTypeDto type; + @JsonProperty("column_id") @Schema(example = "14128033-54b5-4818-a489-21b0dded86e2") private UUID columnId; - @NotNull @JsonProperty("operator_id") @Schema(example = ">") private UUID operatorId; - @NotNull @Schema(example = "1") private String value; - @JsonProperty("is_and") - @Schema(example = "false") - private Boolean isAnd; - } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterTypeDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterTypeDto.java new file mode 100644 index 0000000000..eb9c12f7b2 --- /dev/null +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterTypeDto.java @@ -0,0 +1,28 @@ +package at.tuwien.api.database.query; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema +public enum FilterTypeDto { + + @JsonProperty("where") + WHERE("where"), + + @JsonProperty("or") + OR("or"), + + @JsonProperty("and") + AND("and"); + + private String name; + + FilterTypeDto(String name) { + this.name = name; + } + + @Override + public String toString() { + return this.name; + } +} diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java index 1417036fff..867563cb07 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java @@ -5,7 +5,6 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; -import java.util.List; import java.util.UUID; @Getter @@ -19,8 +18,8 @@ import java.util.UUID; public class OrderDto { @NotNull - @Schema(example = "[\"e891ba86-0258-41a6-a8d9-ff58bc10b618\"]") - private List<UUID> columns; + @Schema(example = "e891ba86-0258-41a6-a8d9-ff58bc10b618") + private UUID column; @Schema(example = "ASC") private OrderTypeDto direction; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SubsetDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SubsetDto.java index 77ef0ffe7e..6e8c238417 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SubsetDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/SubsetDto.java @@ -30,6 +30,6 @@ public class SubsetDto { private List<FilterDto> filter; - private OrderDto order; + private List<OrderDto> order; } diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml index d294d8583b..dec6e42b20 100644 --- a/dbrepo-metadata-service/pom.xml +++ b/dbrepo-metadata-service/pom.xml @@ -8,6 +8,11 @@ <version>3.3.5</version> </parent> + <organization> + <name>TU Wien</name> + <url>https://www.tuwien.ac.at</url> + </organization> + <groupId>at.tuwien</groupId> <artifactId>dbrepo-metadata-service</artifactId> <name>dbrepo-metadata-service</name> @@ -60,8 +65,10 @@ <aws-s3.version>2.25.23</aws-s3.version> <jackson.version>2.15.2</jackson.version> <minio.version>8.5.7</minio.version> - <sonar.coverage.jacoco.xmlReportPaths>./report/target/site/jacoco-aggregate/jacoco.xml + <sonar.coverage.jacoco.xmlReportPaths> + ./report/target/site/jacoco-aggregate/jacoco.xml </sonar.coverage.jacoco.xmlReportPaths> + <CodeCacheSize>128m</CodeCacheSize> </properties> <dependencies> @@ -308,8 +315,25 @@ </goals> </execution> </executions> + </plugin><!-- Surefire runs all Java tests --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <!-- Note config is repeated in scalatest config --> + <configuration> + <argLine>@{argLine} -ea -Xmx4g -Xss4m -XX:MaxMetaspaceSize=2g -XX:ReservedCodeCacheSize=${CodeCacheSize} + </argLine> + </configuration> </plugin> </plugins> </build> + <licenses> + <license> + <name>Apache-2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.html</url> + <distribution>repo</distribution> + </license> + </licenses> + </project> diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java index de510dd970..d711f11a04 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java @@ -520,14 +520,14 @@ public class DatabaseEndpoint extends AbstractEndpoint { .size(); database.setTables(database.getTables() .stream() - .filter(t -> t.getIsPublic() || t.getIsSchemaPublic() || optional.isPresent()) + .filter(t -> t.getIsPublic() || t.getIsSchemaPublic() || optional.isPresent() || isSystem(principal)) .toList()); log.trace("filtered database tables from {} to {}", tables, database.getTables().size()); final int views = database.getViews() .size(); database.setViews(database.getViews() .stream() - .filter(v -> v.getIsPublic() || v.getIsSchemaPublic() || optional.isPresent()) + .filter(v -> v.getIsPublic() || v.getIsSchemaPublic() || optional.isPresent() || isSystem(principal)) .toList()); log.trace("filtered database views from {} to {}", views, database.getViews().size()); if (!isSystem(principal) && !database.getOwner().getId().equals(getId(principal))) { diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/init/weather_at.sql b/dbrepo-metadata-service/rest-service/src/test/resources/init/weather_at.sql index d02e194550..35fd3f88fe 100644 --- a/dbrepo-metadata-service/rest-service/src/test/resources/init/weather_at.sql +++ b/dbrepo-metadata-service/rest-service/src/test/resources/init/weather_at.sql @@ -1,11 +1,17 @@ CREATE -DATABASE weather_at; + DATABASE weather_at; USE -weather_at; + weather_at; CREATE TABLE weather_location ( location VARCHAR(255) PRIMARY KEY, lat DOUBLE PRECISION NULL, lng DOUBLE PRECISION NULL -) WITH SYSTEM VERSIONING COMMENT 'Weather location'; \ No newline at end of file +) WITH SYSTEM VERSIONING COMMENT 'Weather location'; + +INSERT INTO weather_location (location, lat, lng) +VALUES ('Sakhir', 26.0318979, 50.5084668), + ('Fiorano', 44.534308, 10.8551698), + ('Spielberg', 47.219672, 14.7625382), + ('Fuji', 35.3726836, 138.927587); \ No newline at end of file diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java index f78366fe89..6dad07c0be 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java @@ -98,15 +98,18 @@ public abstract class AbstractUnitTest extends BaseTest { /* DATABASE 2 */ DATABASE_2.setSubsets(new LinkedList<>()); DATABASE_2.setAccesses(new LinkedList<>(List.of(DATABASE_2_USER_2_WRITE_ALL_ACCESS, DATABASE_2_USER_3_READ_ACCESS))); - DATABASE_2_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_2_USER_2_WRITE_ALL_ACCESS_DTO, DATABASE_2_USER_3_READ_ACCESS_DTO))); - DATABASE_2_PRIVILEGED_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_2_USER_2_WRITE_ALL_ACCESS_DTO, DATABASE_2_USER_3_READ_ACCESS_DTO))); DATABASE_2.setTables(new LinkedList<>(List.of(TABLE_5, TABLE_6, TABLE_7))); VIEW_4.setColumns(new LinkedList<>(VIEW_4_COLUMNS)); DATABASE_2.setViews(new LinkedList<>(List.of(VIEW_4))); DATABASE_2.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_5))); + DATABASE_2_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_2_USER_2_WRITE_ALL_ACCESS_DTO, DATABASE_2_USER_3_READ_ACCESS_DTO))); DATABASE_2_DTO.setTables(new LinkedList<>(List.of(TABLE_5_DTO, TABLE_6_DTO, TABLE_7_DTO))); DATABASE_2_DTO.setViews(new LinkedList<>(List.of(VIEW_4_DTO))); DATABASE_2_DTO.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_5_DTO))); + DATABASE_2_PRIVILEGED_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_2_USER_2_WRITE_ALL_ACCESS_DTO, DATABASE_2_USER_3_READ_ACCESS_DTO))); + DATABASE_2_PRIVILEGED_DTO.setTables(new LinkedList<>(List.of(TABLE_5_DTO, TABLE_6_DTO, TABLE_7_DTO))); + DATABASE_2_PRIVILEGED_DTO.setViews(new LinkedList<>(List.of(VIEW_4_DTO))); + DATABASE_2_PRIVILEGED_DTO.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_5_DTO))); TABLE_5.setDatabase(DATABASE_2); TABLE_5.setColumns(new LinkedList<>(TABLE_5_COLUMNS)); TABLE_5.setConstraints(TABLE_5_CONSTRAINTS); @@ -138,6 +141,9 @@ public abstract class AbstractUnitTest extends BaseTest { DATABASE_3_DTO.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_6_DTO))); DATABASE_3_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_3_USER_1_WRITE_ALL_ACCESS_DTO))); DATABASE_3_PRIVILEGED_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_3_USER_1_WRITE_ALL_ACCESS_DTO))); + DATABASE_3_PRIVILEGED_DTO.setTables(new LinkedList<>(List.of(TABLE_8_DTO))); + DATABASE_3_PRIVILEGED_DTO.setViews(new LinkedList<>(List.of(VIEW_5_DTO))); + DATABASE_3_PRIVILEGED_DTO.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_6_DTO))); TABLE_8.setDatabase(DATABASE_3); TABLE_8.setColumns(new LinkedList<>(TABLE_8_COLUMNS)); TABLE_8.setConstraints(TABLE_8_CONSTRAINTS); @@ -155,6 +161,8 @@ public abstract class AbstractUnitTest extends BaseTest { DATABASE_4.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_7))); DATABASE_4_DTO.setTables(new LinkedList<>(List.of(TABLE_9_DTO))); DATABASE_4_DTO.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_7_DTO))); + DATABASE_4_PRIVILEGED_DTO.setTables(new LinkedList<>(List.of(TABLE_9_DTO))); + DATABASE_4_PRIVILEGED_DTO.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_7_DTO))); TABLE_9.setDatabase(DATABASE_4); TABLE_9.setColumns(TABLE_9_COLUMNS); TABLE_9.setConstraints(TABLE_9_CONSTRAINTS); diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java index ab2c1e9908..14aefb6ad0 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java @@ -11,7 +11,6 @@ import at.tuwien.api.container.ContainerDto; import at.tuwien.api.container.image.*; import at.tuwien.api.database.*; import at.tuwien.api.database.query.*; -import at.tuwien.api.database.query.FilterDto; import at.tuwien.api.database.table.*; import at.tuwien.api.database.table.columns.*; import at.tuwien.api.database.table.columns.concepts.*; @@ -935,7 +934,7 @@ public abstract class BaseTest { .version(IMAGE_1_VERSION) .isDefault(IMAGE_1_IS_DEFAULT) .jdbcMethod(IMAGE_1_JDBC) - .operators(null) + .operators(null) /* IMAGE_1_OPERATORS_DTO */ .build(); public static final ImageBriefDto IMAGE_1_BRIEF_DTO = ImageBriefDto.builder() @@ -977,6 +976,12 @@ public abstract class BaseTest { .displayName(IMAGE_1_OPERATORS_1_DISPLAY_NAME) .value(IMAGE_1_OPERATORS_1_VALUE) .documentation(IMAGE_1_OPERATORS_1_DOCUMENTATION) + .build(), + OperatorDto.builder() + .id(IMAGE_1_OPERATORS_2_ID) + .displayName(IMAGE_1_OPERATORS_2_DISPLAY_NAME) + .value(IMAGE_1_OPERATORS_2_VALUE) + .documentation(IMAGE_1_OPERATORS_2_DOCUMENTATION) .build())); public static final UUID CONTAINER_1_ID = UUID.fromString("7ddb7e87-b965-43a2-9a24-4fa406d998f4"); @@ -2352,15 +2357,15 @@ public abstract class BaseTest { .build(); public static final UUID TABLE_9_ID = UUID.fromString("9314294f-04fc-4354-8b1f-2a8aeb566453"); - public static final String TABLE_9_NAME = "mfcc"; - public static final String TABLE_9_INTERNAL_NAME = "mfcc"; + public static final String TABLE_9_NAME = "Weather Location"; + public static final String TABLE_9_INTERNAL_NAME = "weather_location"; public static final Boolean TABLE_9_VERSIONED = true; public static final Boolean TABLE_9_IS_PUBLIC = false; public static final Boolean TABLE_9_SCHEMA_PUBLIC = true; public static final Boolean TABLE_9_PROCESSED_CONSTRAINTS = true; - public static final String TABLE_9_DESCRIPTION = "Hello mfcc"; + public static final String TABLE_9_DESCRIPTION = "Location"; public static final String TABLE_9_QUEUE_NAME = TABLE_9_INTERNAL_NAME; - public static final String TABLE_9_ROUTING_KEY = "dbrepo." + DATABASE_3_ID + "." + TABLE_9_ID; + public static final String TABLE_9_ROUTING_KEY = "dbrepo." + DATABASE_4_ID + "." + TABLE_9_ID; public static final Instant TABLE_9_CREATED = Instant.ofEpochSecond(1688400185L) /* 2023-02-26 08:29:35 (UTC) */; public static final Instant TABLE_9_LAST_MODIFIED = Instant.ofEpochSecond(1688400185L) /* 2023-02-26 08:29:35 (UTC) */; @@ -2538,6 +2543,55 @@ public abstract class BaseTest { .build()))) .build(); + public static final UUID QUERY_9_ID = UUID.fromString("df34f0b9-b64c-406c-9109-7a031f4a7f27"); + public static final String QUERY_9_STATEMENT = "SELECT `lat`, `lng` FROM `mfcc` WHERE `location` = 'Fuji'"; + public static final String QUERY_9_QUERY_HASH = "dfcdec827b2ea74d89415f8d1ce39354f59ef304444ba4e12e4f3d9d3f35abe3"; + public static final String QUERY_9_RESULT_HASH = "f0aba070a1fd29e96230d12d7c0b4d08b89820b3cc2dda0575680492010016e7"; + public static final Instant QUERY_9_CREATED = Instant.now().minus(5, MINUTES); + public static final Instant QUERY_9_EXECUTION = Instant.now().minus(1, MINUTES); + public static final Instant QUERY_9_LAST_MODIFIED = Instant.ofEpochSecond(1551588555L); + public static final Long QUERY_9_RESULT_NUMBER = 6L; + public static final Boolean QUERY_9_PERSISTED = true; + + public static final QueryDto QUERY_9_DTO = QueryDto.builder() + .id(QUERY_9_ID) + .databaseId(DATABASE_3_ID) + .query(QUERY_9_STATEMENT) + .queryNormalized(QUERY_9_STATEMENT) + .resultNumber(QUERY_9_RESULT_NUMBER) + .resultHash(QUERY_9_RESULT_HASH) + .queryHash(QUERY_9_QUERY_HASH) + .execution(QUERY_9_EXECUTION) + .isPersisted(QUERY_9_PERSISTED) + .owner(USER_1_BRIEF_DTO) + .build(); + + public static final SubsetDto QUERY_9_SUBSET_DTO = SubsetDto.builder() + .tableId(TABLE_9_ID) + .columns(new LinkedList(List.of(COLUMN_9_2_ID, COLUMN_9_3_ID))) + .filter(new LinkedList(List.of(FilterDto.builder() + .columnId(COLUMN_9_1_ID) + .operatorId(IMAGE_1_OPERATORS_2_ID) + .value("Fuji") + .type(FilterTypeDto.WHERE) + .build()))) + .build(); + + public static final ViewDto QUERY_9_VIEW_DTO = ViewDto.builder() + .vdbid(DATABASE_4_ID) + .query(QUERY_9_STATEMENT) + .queryHash(QUERY_9_QUERY_HASH) + .owner(USER_1_BRIEF_DTO) + .columns(new LinkedList<>(List.of(ViewColumnDto.builder() + .name("lat") + .internalName("lat") + .build(), + ViewColumnDto.builder() + .name("lng") + .internalName("lng") + .build()))) + .build(); + public static final String QUEUE_NAME = "dbrepo"; public static final String QUEUE_VHOST = "dbrepo"; public static final Boolean QUEUE_AUTO_DELETE = false; @@ -2845,11 +2899,11 @@ public abstract class BaseTest { public static final SubsetDto QUERY_1_SUBSET_DTO = SubsetDto.builder() .tableId(TABLE_1_ID) - .columns(new LinkedList(List.of(COLUMN_1_1_ID, COLUMN_1_2_ID, COLUMN_1_3_ID, COLUMN_1_4_ID, COLUMN_1_5_ID))) - .order(OrderDto.builder() - .columns(new LinkedList(List.of(COLUMN_1_1_ID))) + .columns(new LinkedList<UUID>(List.of(COLUMN_1_1_ID, COLUMN_1_2_ID, COLUMN_1_3_ID, COLUMN_1_4_ID, COLUMN_1_5_ID))) + .order(new LinkedList<OrderDto>(List.of(OrderDto.builder() + .column(COLUMN_1_1_ID) .direction(OrderTypeDto.ASC) - .build()) + .build()))) .build(); public static final ViewDto QUERY_1_VIEW_DTO = ViewDto.builder() @@ -2903,7 +2957,7 @@ public abstract class BaseTest { public static final QueryDto QUERY_2_DTO = QueryDto.builder() .id(QUERY_2_ID) - .databaseId(DATABASE_2_ID) + .databaseId(DATABASE_1_ID) .query(QUERY_2_STATEMENT) .queryNormalized(QUERY_2_STATEMENT) .resultNumber(QUERY_2_RESULT_NUMBER) @@ -2977,6 +3031,7 @@ public abstract class BaseTest { public static final QueryDto QUERY_4 = QueryDto.builder() .id(QUERY_4_ID) + .databaseId(DATABASE_3_ID) .query(QUERY_4_STATEMENT) .queryHash(QUERY_4_QUERY_HASH) .resultHash(QUERY_4_RESULT_HASH) @@ -3048,9 +3103,10 @@ public abstract class BaseTest { .tableId(TABLE_8_ID) .columns(new LinkedList(List.of(COLUMN_8_1_ID, COLUMN_8_2_ID))) .filter(new LinkedList(List.of(FilterDto.builder() - .columnId(COLUMN_8_2_ID) - .operatorId(IMAGE_1_OPERATORS_2_ID) + .columnId(COLUMN_8_2_ID) + .operatorId(IMAGE_1_OPERATORS_2_ID) .value("0") + .type(FilterTypeDto.WHERE) .build()))) .build(); @@ -3090,7 +3146,7 @@ public abstract class BaseTest { public static final QueryDto QUERY_6_DTO = QueryDto.builder() .id(QUERY_6_ID) - .databaseId(DATABASE_2_ID) + .databaseId(DATABASE_1_ID) .query(QUERY_6_STATEMENT) .queryNormalized(QUERY_6_STATEMENT) .resultNumber(QUERY_6_RESULT_NUMBER) @@ -4770,6 +4826,47 @@ public abstract class BaseTest { .constraints(TABLE_5_CONSTRAINTS_INVALID_CREATE) .build(); + public static final UUID QUERY_8_ID = UUID.fromString("1c466eee-d551-4ef9-a7e0-b5a2d1b15473"); + public static final String QUERY_8_STATEMENT = "SELECT `id`, `animal_name` FROM `zoo` WHERE `hair` = TRUE AND `feathers` = FALSE;"; + public static final String QUERY_8_QUERY_HASH = "f0ee0d6dd45e092fca120c4f0eab089f91ed26ccf8dc34a03c6b9c6bb4141271"; + public static final Long QUERY_8_RESULT_NUMBER = 5L; + public static final String QUERY_8_RESULT_HASH = "b5f9cae916d32deff81c5f2e9f8ff43904034bc084b12320730953d120698bed"; + public static final Instant QUERY_8_EXECUTION = Instant.now().minus(1, MINUTES); + public static final Boolean QUERY_8_PERSISTED = true; + + public static final QueryDto QUERY_8_DTO = QueryDto.builder() + .id(QUERY_8_ID) + .databaseId(DATABASE_2_ID) + .query(QUERY_8_STATEMENT) + .queryNormalized(QUERY_8_STATEMENT) + .resultNumber(QUERY_8_RESULT_NUMBER) + .resultHash(QUERY_8_RESULT_HASH) + .owner(USER_1_BRIEF_DTO) + .queryHash(QUERY_8_QUERY_HASH) + .execution(QUERY_8_EXECUTION) + .isPersisted(QUERY_8_PERSISTED) + .resultNumber(3L) + .build(); + + public static final SubsetDto QUERY_8_SUBSET_DTO = SubsetDto.builder() + .tableId(TABLE_5_ID) + .columns(new LinkedList<>(List.of(COLUMN_5_1_ID, COLUMN_5_2_ID))) + .filter(new LinkedList<>(List.of(FilterDto.builder() + .columnId(COLUMN_5_3_ID) + .operatorId(IMAGE_1_OPERATORS_2_ID) + .value("true") + .type(FilterTypeDto.WHERE) + .build(), + FilterDto.builder() + .type(FilterTypeDto.AND) + .build(), + FilterDto.builder() + .columnId(COLUMN_5_4_ID) + .operatorId(IMAGE_1_OPERATORS_2_ID) + .value("false") + .build()))) + .build(); + public static final UUID COLUMN_6_1_ID = UUID.fromString("27b04a64-2849-4fae-b295-858c3e50361f"); public static final UUID COLUMN_6_2_ID = UUID.fromString("1ea62e32-5719-4152-94da-45d37eb88b6f"); diff --git a/dbrepo-ui/assets/globals.css b/dbrepo-ui/assets/globals.css index 52da2e48c8..90dc2854d0 100644 --- a/dbrepo-ui/assets/globals.css +++ b/dbrepo-ui/assets/globals.css @@ -10,4 +10,7 @@ select.native { border-style: solid; width: 100%; } +.line-break { + white-space: pre-wrap; } + /*# sourceMappingURL=globals.css.map */ diff --git a/dbrepo-ui/assets/globals.css.map b/dbrepo-ui/assets/globals.css.map index 6f271c8f99..13ee94918a 100644 --- a/dbrepo-ui/assets/globals.css.map +++ b/dbrepo-ui/assets/globals.css.map @@ -1,6 +1,6 @@ { "version": 3, -"mappings": "AAAA,CAAE;EACA,KAAK,EAAE,sBAAsB;;AAG/B;aACc;EACZ,OAAO,EAAE,KAAK;;AAGhB,aAAc;EACZ,kBAAkB,EAAE,OAAO;EAC3B,YAAY,EAAE,KAAK;EACnB,KAAK,EAAE,IAAI", +"mappings": "AAAA,CAAE;EACA,KAAK,EAAE,sBAAsB;;AAG/B;aACc;EACZ,OAAO,EAAE,KAAK;;AAGhB,aAAc;EACZ,kBAAkB,EAAE,OAAO;EAC3B,YAAY,EAAE,KAAK;EACnB,KAAK,EAAE,IAAI;;AAGb,WAAY;EACV,WAAW,EAAE,QAAQ", "sources": ["globals.scss"], "names": [], "file": "globals.css" diff --git a/dbrepo-ui/assets/globals.scss b/dbrepo-ui/assets/globals.scss index 5d4d4e06a7..5e0dce3a0f 100644 --- a/dbrepo-ui/assets/globals.scss +++ b/dbrepo-ui/assets/globals.scss @@ -12,3 +12,7 @@ select.native { border-style: solid; width: 100%; } + +.line-break { + white-space: pre-wrap; +} diff --git a/dbrepo-ui/components/identifier/Summary.vue b/dbrepo-ui/components/identifier/Summary.vue index 6ef120599b..dcbe2f063d 100644 --- a/dbrepo-ui/components/identifier/Summary.vue +++ b/dbrepo-ui/components/identifier/Summary.vue @@ -26,7 +26,7 @@ <v-list-item :title="$t('pages.identifier.descriptions.title')" density="compact"> - <p + <div v-for="(description, i) in identifier.descriptions" :key="`d-${i}`"> <div @@ -36,7 +36,7 @@ <span> {{ description.description }} </span> - </p> + </div> </v-list-item> <v-list-item :title="$t('pages.identifier.publisher.title')" diff --git a/dbrepo-ui/components/subset/Builder.vue b/dbrepo-ui/components/subset/Builder.vue index 924b4f3e0c..650d47570e 100644 --- a/dbrepo-ui/components/subset/Builder.vue +++ b/dbrepo-ui/components/subset/Builder.vue @@ -148,7 +148,15 @@ variant="flat" :text="$t('pages.subset.subpages.create.filter.text')" :disabled="clausesDisabled" - @click="addFirst" /> + @click="addFirstFilter" /> + <v-btn + v-if="sort.length === 0" + size="small" + color="secondary" + variant="flat" + :text="$t('pages.subset.subpages.create.order.text')" + :disabled="clausesDisabled" + @click="addFirstSort" /> </v-col> </v-row> <div class="mb-5"> @@ -292,6 +300,7 @@ export default { table: null, views: [], columns: [], + sort: [], timestamp: null, executeDifferentTimestamp: false, dataOptions: [ @@ -403,9 +412,15 @@ export default { table_id: this.table.id, columns: this.select.map(column => column.id), filter: this.clauses.map(clause => { + if (clause.type === 'or' || clause.type === 'and') { + return { + type: clause.type + } + } const filtered_column = this.table.columns.filter(column => column.internal_name === clause.params[0]) const filtered_operator = this.database.container.image.operators.filter(operator => operator.value === clause.params[1]) const json = { + type: clause.type, column_id: filtered_column[0].id, operator_id: filtered_operator[0].id, value: clause.params[2] @@ -510,6 +525,7 @@ export default { this.loadingQuery = false const toast = useToastInstance() if (typeof code !== 'string') { + toast.error(this.$t('error.query.invalid')) return } toast.error(`${this.$t(code)}: ${message}`) @@ -551,17 +567,21 @@ export default { canAdd (idx) { return idx === this.clauses.length - 1 }, - addFirst () { + addFirstFilter () { const column = (this.columnNames && this.columnNames.length) ? this.columnNames[0] : '' this.clauses.push({ type: 'where', params: [column, '=', ''] }) }, + addFirstSort () { + const column = (this.columnNames && this.columnNames.length) ? this.columnNames[0] : '' + this.sort.push({ column_id: null, direction: 'asc' }) + }, addAnd () { this.clauses.push({ type: 'and' }) - this.addFirst() + this.addFirstFilter() }, addOr () { this.clauses.push({ type: 'or' }) - this.addFirst() + this.addFirstFilter() }, remove (idx) { if (idx === 0) { diff --git a/dbrepo-ui/composables/query-service.ts b/dbrepo-ui/composables/query-service.ts index c0d5c0db7c..3d05b9a3cd 100644 --- a/dbrepo-ui/composables/query-service.ts +++ b/dbrepo-ui/composables/query-service.ts @@ -1,4 +1,3 @@ -import {format} from 'sql-formatter' import type {AxiosRequestConfig} from 'axios' import {axiosErrorToApiError} from '@/utils' @@ -191,11 +190,7 @@ export const useQueryService = (): any => { error: false, reason: null, column: null, - raw: sql, - formatted: format(sql, { - language: 'mysql', - keywordCase: 'upper' - }) + raw: sql } } diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json index a42a56411b..1c4298e9b4 100644 --- a/dbrepo-ui/locales/en-US.json +++ b/dbrepo-ui/locales/en-US.json @@ -1015,6 +1015,9 @@ "or": { "text": "Add \"OR\" Filter" } + }, + "order": { + "text": "Add Sorting" } } } diff --git a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue index d3b5f624d7..5c95a844d7 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue @@ -50,7 +50,8 @@ <v-list-item :title="$t('pages.subset.query.title')" density="compact"> - <pre>{{ subset.query }}</pre> + <pre + class="line-break">{{ subset.query }}</pre> </v-list-item> <v-list-item :title="`${$t('pages.subset.query.title')} ${$t('pages.subset.hash.title')}`" diff --git a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue index 395be401c0..b5266b79f2 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/[view_id]/info.vue @@ -32,7 +32,8 @@ </v-list-item> <v-list-item :title="$t('pages.view.query.title')"> - <pre>{{ view.query }}</pre> + <pre + class="line-break">{{ view.query }}</pre> </v-list-item> <v-list-item :title="$t('pages.view.owner.title')"> diff --git a/helm/dbrepo/files/create-event-listener.jar b/helm/dbrepo/files/create-event-listener.jar index cd7f74508b8bee100bac98aac20c40f44ddd150d..70fca91e2c62b6c899e74332a8e1398e9c8c4b75 100644 GIT binary patch delta 695 zcmbQ^KgVAvz?+#xgn@yBgF!zaCQ3p^J8PnlQoV2RVFiJ`>1zKQ?HN>-$<La7wYe;6 z?#gSw+03S8I$3S-e7k@8GO6Qzi{%<xYu{AwN#(pY<wfWI1)rB~wDfirayRE|4ETIg zG2Q#cg-zMZ&6YVIH!`$RN?W_qWd3X2`dbURt}iPr>G8=F30QGtK5ys@<5-J3rZQ2t z3i{U>bDf`9&-~pr{+CT=>Ej}^`KI?aKROV$;-+kX%-!p|xw5x>F~2YQMS7vc{|W!q zpI2=?akDMsd9mjA-+K*~ieGuh8^!3w;F;{rJ}+kViqaQPJ?Hf-PWYmtQ~V;~!S17n z8f5wGt%cUqe))5wagO6!^~H7n8A>bO9lG&t?S1|qogB7LB2U@ZZ}4CB%)EE&iWTRp zL!Ym2`=yvV!#r0pB>1$hT*%b}WgIRZURVFK_QhV1kvpgTm{WIG@I%qEXD-ocCwKTP zzpUfCZqkz=O^+`XC5D%7N~i~W2y9Z?>tt~^diSf-JMWu#6m@LklUwxr(j{)rCc7;x z%8y^jg5rUTfq{bo6c3X(GO94^1;k9g!Ke$SIhf?Yv?h}(vwlF#<Ul4ZFkQ!F0;abz zd4c7bn9qXgOU&IMdUFEH940X1KN~kEn87PBix;e=M{(BX<+6{M!5mGc$sDlwpL|5g z3M|N|Yy#3U*+SVCOjjuDf$5dXreOJp$`EyODlTAts!9}C{*X#An3hn@1=Ag>v0(az zsw0@zQ40gBf2k%td4Zbw<O_;iYysYkOd`ya7s^WUFhIeQMk~3=y-d=R?=y)_zN{t; J))S)c0RW)p5WoNc delta 719 zcmbQ^KgVAvz?+#xgn@yBgCS&fR8(%=kA{gtO7#be4k-xiO;`JWfS<uFS*m#Tw+mLc z&Skuvd*GIV+L1=zHTCg5W`1-1ZZmJ#&|llXU8nV8bb-hH16HxKdt7n^*o?WE9522! zRQA5ur1(8dY!|Dyn~t60vR*yWxvOPk-#h-wE>A4z`V!{dxKF6|YJ`(pNM2%m@Wlj2 z*&AWrJ6!9(-8sDOOYWr=x6)GV*3MP_IdP4{MEAzT4<T>8R~&e7zsCGReoM|D=YR9( z%)Y9m%=+kF>Ku7K_GR1q5{oY+%$VS#a6K)%)%mtZj*dm$wBv^lNYDL|suy+fv#rCr z)|dSItsbqdE&Ot&v8TgJwQzgA*wp%WPP3mazWx12%TKvWfiCs>H@2>MvBr!|rL0nY z^_$pabBpiA7oYfC6TN>haN5=zUl~7p>h0d|u<+}wzlSqd$~G}p>+NX@o1d9DL#=R? z+GGu>XF```*tF!1G0!~pu|g$;h3kpM%sKCKb1F;Une)o%GOXXzp0Ga3N-^$&Yqz-( zj~yc@9=I47I2b_jFnJ@R3Ul!4sL3}Nb-^?TlN^}VWKv}gSsgVwkVy+n*D;xZ>8(s& zV0k9yvtarXb2o_IoWL@N3C#G<#?1+4@CwZ0-RvUwh#9PJmFz4qt*JDb0~Y_2k0@Dz z1sRo1Kw2hSDBFVR3S~Voy;9i}EdNj$qE1f51<X%Xi2}<XQV9mr5~{gix<fS<OutZd z1k*ZdVUypg$xU9MX0Bh6n-k#8$RxsyNQ1lAJxFq5U|;}YTLuJJ(paxJnOEI(@;g~B Lel$&!L)1M0J#run -- GitLab From f710cd744005c52e27a8c9023d87aec480ae2457 Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Fri, 28 Feb 2025 14:03:09 +0100 Subject: [PATCH 04/11] WIP Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- .../target/create-event-listener.jar | Bin 10140 -> 10140 bytes .../java/at/tuwien/mapper/MariaDbMapper.java | 7 +- .../tuwien/api/database/query/OrderDto.java | 4 +- .../main/java/at/tuwien/test/BaseTest.java | 2 +- .../components/container/ContainerCard.vue | 11 +- dbrepo-ui/components/identifier/Persist.vue | 2 +- dbrepo-ui/components/subset/Builder.vue | 155 +++++++++++++----- dbrepo-ui/components/subset/SubsetToolbar.vue | 2 +- dbrepo-ui/components/table/TableToolbar.vue | 2 +- dbrepo-ui/components/view/ViewToolbar.vue | 2 +- dbrepo-ui/composables/query-service.ts | 65 +------- dbrepo-ui/dto/index.ts | 26 ++- dbrepo-ui/locales/en-US.json | 8 +- dbrepo-ui/nuxt.config.ts | 1 - .../[database_id]/subset/[subset_id]/info.vue | 4 +- helm/dbrepo/files/01-setup-schema.sql | 20 +-- helm/dbrepo/files/create-event-listener.jar | Bin 10140 -> 10140 bytes 17 files changed, 172 insertions(+), 139 deletions(-) diff --git a/dbrepo-auth-service/listeners/target/create-event-listener.jar b/dbrepo-auth-service/listeners/target/create-event-listener.jar index 70fca91e2c62b6c899e74332a8e1398e9c8c4b75..a3214b6c85649309e39ba6f970febd743621219e 100644 GIT binary patch delta 692 zcmbQ^KgVAvz?+#xgn@yBgTbpHCTc0u?yVDrl<H6C9WoHu<9^Ei2YZe)uj9$JTiV4O zwJ#p8eVo(f`beQ#_|*ODEoLiLWL0n2`>n71*ygxKQ`M?R>tF22%sF-}NyOcpuW`eJ z&(6ofE-XyF?w9Y=-lu73sq}2^O0Inx+x}#>TgA*ideP8m=|zWyLiJ`LiO0I`JY4ti z!lkzAlDQWv>N{n2tp9asx@WYBUUGNkW82gGIlZjAnY$MMt_n}=o%Zk9?uI&Lk<0R* z{y(XS)HmLyc<ZOnslRplJ}+6fRyT(=h&f!kaj8-LdRCTfRpli0#~KoITT&Tid1|)L zklt|kVYqwK*8X|&))Nd@bf;W;FTa5Ae5};%ecyjG&hNP3yzW^2AK~9ivg<BKbkF*= z=X&Y4v=#C}ZIzdwIhk+0^T;urH>cg9WyzJl@egjWo_+XmkI}pfi>yWClGFXRtdwHZ zka!y4cS^<gifEtk(li6lbk~(3R=%REGK+S7f3#|I@&3#SPXtnBZCuK)UE=0!vfIj{ z{P+bkC?2>N7&sU}@i2KKqY9Hp!Q|_VdQ6@Lli8W%L6ioQ8k1MS<NzjZ5LL@$3Zk|! zd4p6kGM@uc7nysQJPS6*v&>}z(f`<ZI6*Xzz-->lE^?2UK{{5-&IVB$N>eysQ9k*I zk`<Fz!6ao<kRj&Eb|CA@mGwc?3S~2p@(0S+AWBxn6-1?|M1xcwR0#o5;;MNdmF=o= zAnLiQ6Nu7Q3!nT}O>Xi6HFN!n+?)V!MkWzvL`vJe?m?0h0|NsH+cF@)lE!+)$-L^O Qli$g5@u6y(9IWmM0OdLrM*si- delta 667 zcmbQ^KgVAvz?+#xgn@yBgF!zaCQ3p^J8PnlQoV2RVFiJ`>1zKQ?HN>-$<La7wYe;6 z?#gSw+03S8I$3S-e7k@8GO6Qzi{%<xYu{AwN#(pY<wfWI1)rB~wDfirayRE|4ETIg zG2Q#cg-zMZ&6YVIH!`$RN?W_qWd3X2`dbURt}iPr>G8=F30QGtK5ys@<5-J3rZQ2t z3i{U>bDf`9&-~pr{+CT=>Ej}^`KI?aKROV$;-+kX%-!p|xw5x>F~2YQMS7vc{|W!q zpI2=?akDMsd9mjA-+K*~ieGuh8^!3w;F;{rJ}+kViqaQPJ?Hf-PWYmtQ~V;~!S17n z8f5wGt%cUqe))5wagO6!^~H7n8A>bO9lG&t?S1|qogB7LB2U@ZZ}4CB%)EE&iWTRp zL!Ym2`=yvV!#r0pB>1$hT*%b}WgIRZURVFK_QhV1kvpgTm{WIG@I%qEXD-ocCwKTP zzpUfCZqkz=O^+`XC5D%7N~i~W2y9Z?>tt~^diSf-JMWu#6m@LklUwxr(j{)rCc7;x z%8y^jg5rUTfq{bo6c3X(GO94?1x&uqs0X6hndCu~29p|-e!%1aCT$Q^%VY|owlH~v z<QSRHfvAhjJxqE5o8wvLGJ)uSY&@JGnnz$ZFGz8>;_S`KWgjtv*cwVxIABpe`G}Gg zlYYP?WmAwL=E`;;s$5wgM6FOZ11W!?Yz?AhRa`+-ib^y{?x0Eth!R)L15xd&aUkls zsuPIPRtpEIe4!>Yd4Zbw<O_;iYysYkOd`ya7s^WUFhIeQMk~3=y-d=R?=y)_zN{t; J(h{uh2>>c)2Jip? diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java index d7250ccc74..3c87b5a9fa 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java @@ -870,12 +870,15 @@ public interface MariaDbMapper { SubsetDto data) throws TableNotFoundException { final List<OrderField<Object>> sort = new LinkedList<>(); for (OrderDto order : data.getOrder()) { - final ColumnDto column = columnIdToColumnDto(database, order.getColumn()); + final ColumnDto column = columnIdToColumnDto(database, order.getColumnId()); + if (order.getDirection() == null) { + sort.add(field(column.getInternalName())); + continue; + } switch (order.getDirection()) { case ASC -> sort.add(field(column.getInternalName()).asc()); case DESC -> sort.add(field(column.getInternalName()).desc()); } - sort.add(field(column.getInternalName())); } return step.orderBy(sort); } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java index 867563cb07..7a14b50c20 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java @@ -1,5 +1,6 @@ package at.tuwien.api.database.query; +import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.*; @@ -18,8 +19,9 @@ import java.util.UUID; public class OrderDto { @NotNull + @JsonProperty("column_id") @Schema(example = "e891ba86-0258-41a6-a8d9-ff58bc10b618") - private UUID column; + private UUID columnId; @Schema(example = "ASC") private OrderTypeDto direction; diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java index 14aefb6ad0..193ef916c7 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java @@ -2901,7 +2901,7 @@ public abstract class BaseTest { .tableId(TABLE_1_ID) .columns(new LinkedList<UUID>(List.of(COLUMN_1_1_ID, COLUMN_1_2_ID, COLUMN_1_3_ID, COLUMN_1_4_ID, COLUMN_1_5_ID))) .order(new LinkedList<OrderDto>(List.of(OrderDto.builder() - .column(COLUMN_1_1_ID) + .columnId(COLUMN_1_1_ID) .direction(OrderTypeDto.ASC) .build()))) .build(); diff --git a/dbrepo-ui/components/container/ContainerCard.vue b/dbrepo-ui/components/container/ContainerCard.vue index ed1479f64d..841333c44d 100644 --- a/dbrepo-ui/components/container/ContainerCard.vue +++ b/dbrepo-ui/components/container/ContainerCard.vue @@ -17,7 +17,7 @@ height="20" class="font-small"> <template v-slot:default> - {{ container.count }} / {{ container.quota }} + {{ container.count }} / {{ quota }} </template> </v-progress-linear> </v-card-text> @@ -39,7 +39,16 @@ export default { } }, computed: { + quota () { + if (!this.container || !this.container.quota) { + return '∞' + } + return this.container.quota + }, utilization () { + if (!this.container || !this.container.quota) { + return 0 + } return this.container.count * 100.0 / this.container.quota }, colorVariant () { diff --git a/dbrepo-ui/components/identifier/Persist.vue b/dbrepo-ui/components/identifier/Persist.vue index f228eade28..004a037c46 100644 --- a/dbrepo-ui/components/identifier/Persist.vue +++ b/dbrepo-ui/components/identifier/Persist.vue @@ -34,7 +34,7 @@ <v-btn v-if="canPublish" class="mr-2" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-content-save-outline' : null" + :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-identifier' : null" color="primary" variant="flat" :loading="loadingPublish" diff --git a/dbrepo-ui/components/subset/Builder.vue b/dbrepo-ui/components/subset/Builder.vue index 650d47570e..6f13e07273 100644 --- a/dbrepo-ui/components/subset/Builder.vue +++ b/dbrepo-ui/components/subset/Builder.vue @@ -25,7 +25,7 @@ <v-card-text> <v-form ref="form" - @submit.prevent> + @submit.prevent="$refs.form.validate()"> <v-row v-if="isView" class="mt-1" @@ -110,12 +110,13 @@ item-title="internal_name" :disabled="!table || isExecuted" :items="columns" + :rules="[v => !!v || $t('validation.required')]" + required persistent-hint clearable :variant="inputVariant" :label="$t('pages.view.subpages.create.columns.label')" :hint="$t('pages.view.subpages.create.columns.hint')" - :rules="[v => !!v || $t('validation.required')]" :loading="loadingColumns" return-object multiple> @@ -144,22 +145,24 @@ <v-btn v-if="clauses.length === 0" size="small" - color="secondary" + color="tertiary" variant="flat" :text="$t('pages.subset.subpages.create.filter.text')" :disabled="clausesDisabled" @click="addFirstFilter" /> <v-btn - v-if="sort.length === 0" + v-if="clauses.length === 0 && sorts.length === 0" + class="ml-2" size="small" - color="secondary" + color="tertiary" variant="flat" :text="$t('pages.subset.subpages.create.order.text')" :disabled="clausesDisabled" @click="addFirstSort" /> </v-col> </v-row> - <div class="mb-5"> + <div + class="mb-5"> <v-row v-if="clauses.length > 0"> <v-col @@ -179,6 +182,9 @@ item-title="internal_name" item-value="internal_name" variant="underlined" + :rules="[v => !!v || $t('validation.required')]" + required + clearable persistent-hint :label="$t('pages.subset.subpages.create.filter.column.label')" :hint="$t('pages.subset.subpages.create.filter.column.hint')" @@ -191,9 +197,12 @@ :disabled="clausesDisabled" item-title="value" item-value="value" + :rules="[v => !!v || $t('validation.required')]" + required + clearable persistent-hint - :label="operatorHint(clause.params[1])" - :hint="$t('pages.subset.subpages.create.filter.operator.label')" + :label="$t('pages.subset.subpages.create.filter.operator.label')" + :hint="operatorHint(clause.params[1])" :items="operators"> <template v-slot:append> @@ -219,6 +228,9 @@ <v-text-field v-model="clause.params[2]" :disabled="clausesDisabled" + :rules="[v => !!v || $t('validation.required')]" + required + clearable persistent-hint :label="$t('pages.subset.subpages.create.filter.value.label')" :hint="$t('pages.subset.subpages.create.filter.value.hint')" /> @@ -232,7 +244,7 @@ color="error" variant="flat" :text="$t('pages.subset.subpages.create.filter.remove.text')" - @click="remove(idx)" /> + @click="removeFilter(idx)" /> </v-col> </v-row> <v-row @@ -252,7 +264,7 @@ :disabled="!canAdd(idx) || clausesDisabled" class="mt-2 mr-1" variant="flat" - color="secondary" + color="tertiary" size="small" :text="$t('pages.subset.subpages.create.filter.and.text')" @click="addAnd" /> @@ -260,7 +272,7 @@ :disabled="!canAdd(idx) || clausesDisabled" class="mt-2" variant="flat" - color="secondary" + color="tertiary" size="small" :text="$t('pages.subset.subpages.create.filter.or.text')" @click="addOr" /> @@ -269,6 +281,72 @@ </div> </div> </div> + <div class="mb-5"> + <v-row + v-if="sorts.length > 0"> + <v-col + lg="8" + class="text-center"> + <pre>SORT BY</pre> + </v-col> + </v-row> + <v-row + v-for="(sort, idx) in sorts" + key="idx"> + <v-col + lg="4"> + <v-select + v-model="sort.column_id" + :disabled="clausesDisabled" + item-title="internal_name" + item-value="id" + :rules="[v => !!v || $t('validation.required')]" + required + clearable + variant="underlined" + persistent-hint + :label="$t('pages.subset.subpages.create.filter.column.label')" + :hint="$t('pages.subset.subpages.create.filter.column.hint')" + :items="columns" /> + </v-col> + <v-col + lg="4"> + <v-select + v-model="sort.direction" + :disabled="clausesDisabled" + item-title="title" + item-value="value" + clearable + persistent-hint + :label="$t('pages.subset.subpages.create.order.direction.label')" + :items="sortings" /> + </v-col> + <v-col + lg="1"> + <v-btn + :disabled="clausesDisabled" + class="mt-4" + size="small" + color="error" + variant="flat" + :text="$t('pages.subset.subpages.create.order.remove.text')" + @click="removeSort(idx)" /> + </v-col> + </v-row> + </div> + <v-row + v-if="(sorts.length > 0 || clauses.length > 0) && select.length > 0"> + <v-col + lg="8"> + <v-btn + size="small" + color="tertiary" + variant="flat" + :text="$t('pages.subset.subpages.create.order.text')" + :disabled="clausesDisabled" + @click="addFirstSort" /> + </v-col> + </v-row> </v-window-item> </v-window> </v-form> @@ -300,7 +378,7 @@ export default { table: null, views: [], columns: [], - sort: [], + sorts: [], timestamp: null, executeDifferentTimestamp: false, dataOptions: [ @@ -313,7 +391,6 @@ export default { ], tableDetails: null, resultId: null, - valid: false, errorKeyword: null, query: { table_id: null, @@ -328,6 +405,10 @@ export default { select: [], clauses: [], tabs: 0, + sortings: [ + { title: 'Ascending ↓', value: 'asc' }, + { title: 'Descening ↑', value: 'desc' }, + ], loadingQuery: false, loadingColumns: false, cacheStore: useCacheStore() @@ -379,39 +460,20 @@ export default { isExecuted () { return this.resultId !== null }, - valid () { - if (this.isView) { - return this.valid && !this.hasUnsupported - } - return this.sql.length > 0 && !this.hasUnsupported - }, unsupported () { if (!this.$config.public.database.unsupported) { return [] } return this.$config.public.database.unsupported.split(',') }, - hasUnsupported () { - if (!this.sql) { - return false - } - const unsupported = this.unsupported.map(k => k.toLowerCase()) - for (let i = 0; i < unsupported.length; i++) { - if (this.sql.toLowerCase().includes(unsupported[i])) { - console.warn('query contains unsupported keyword', unsupported[i]) - return true - } - } - return this.sql.includes(';') - }, subset () { - if (!this.table || !this.select || !this.clauses) { + if (!this.table || !this.select) { return null } return { table_id: this.table.id, columns: this.select.map(column => column.id), - filter: this.clauses.map(clause => { + filter: this.clauses ? this.clauses.map(clause => { if (clause.type === 'or' || clause.type === 'and') { return { type: clause.type @@ -419,6 +481,9 @@ export default { } const filtered_column = this.table.columns.filter(column => column.internal_name === clause.params[0]) const filtered_operator = this.database.container.image.operators.filter(operator => operator.value === clause.params[1]) + if (!filtered_column || filtered_column.length === 0 || !filtered_operator || filtered_operator.length === 0) { + return null + } const json = { type: clause.type, column_id: filtered_column[0].id, @@ -426,14 +491,15 @@ export default { value: clause.params[2] } return json - }) + }) : null, + order: this.sorts } }, canExecute () { if (this.isView) { return this.view.name !== null && this.view.is_public !== null && this.subset !== null } - return this.subset !== null + return this.subset !== null && this.subset.columns && this.subset.columns.length > 0 && this.$refs.form.isValid }, inputVariant () { const runtimeConfig = useRuntimeConfig() @@ -570,10 +636,11 @@ export default { addFirstFilter () { const column = (this.columnNames && this.columnNames.length) ? this.columnNames[0] : '' this.clauses.push({ type: 'where', params: [column, '=', ''] }) + this.$refs.form.validate() }, addFirstSort () { - const column = (this.columnNames && this.columnNames.length) ? this.columnNames[0] : '' - this.sort.push({ column_id: null, direction: 'asc' }) + this.sorts.push({ column_id: this.select[0].id, direction: 'asc' }) + this.$refs.form.validate() }, addAnd () { this.clauses.push({ type: 'and' }) @@ -583,7 +650,7 @@ export default { this.clauses.push({ type: 'or' }) this.addFirstFilter() }, - remove (idx) { + removeFilter (idx) { if (idx === 0) { if (this.clauses.length === 1) { this.clauses.splice(idx, 1) @@ -595,6 +662,14 @@ export default { this.clauses.splice(idx - 1, 2) } }, + removeSort (idx) { + if (idx === 0) { + this.sorts.splice(idx, 1) + } else { + // remove current and previous + this.sorts.splice(idx - 1, 1) + } + }, toggleColumns () { if (this.select.length !== this.columns.length) { this.select = this.columns @@ -611,7 +686,7 @@ export default { }, operatorHint (value) { const filter = this.operators.filter(o => o.value === value) - if (filter.length !== 1) { + if (filter.length !== 1 || filter[0].display_name === filter[0].value) { return null } return filter[0].display_name diff --git a/dbrepo-ui/components/subset/SubsetToolbar.vue b/dbrepo-ui/components/subset/SubsetToolbar.vue index 2e6dae6302..070cdb4a3b 100644 --- a/dbrepo-ui/components/subset/SubsetToolbar.vue +++ b/dbrepo-ui/components/subset/SubsetToolbar.vue @@ -34,7 +34,7 @@ color="primary" variant="flat" class="mr-2" - :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-content-save-outline' : null" + :prepend-icon="$vuetify.display.lgAndUp ? 'mdi-identifier' : null" :to="`/database/${$route.params.database_id}/subset/${$route.params.subset_id}/persist`"> {{ ($vuetify.display.lgAndUp ? $t('toolbars.subset.pid.xl') + ' ' : '') + $t('toolbars.subset.pid.permanent') }} </v-btn> diff --git a/dbrepo-ui/components/table/TableToolbar.vue b/dbrepo-ui/components/table/TableToolbar.vue index e09cd67cba..7311e0afd5 100644 --- a/dbrepo-ui/components/table/TableToolbar.vue +++ b/dbrepo-ui/components/table/TableToolbar.vue @@ -48,7 +48,7 @@ :to="`/database/${$route.params.database_id}/view/create?tid=${$route.params.table_id}`" /> <v-btn v-if="canGetPid" - :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-content-save-outline' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-identifier' : null" color="primary" variant="flat" :text="($vuetify.display.mdAndUp ? 'Get ' : '') + 'PID'" diff --git a/dbrepo-ui/components/view/ViewToolbar.vue b/dbrepo-ui/components/view/ViewToolbar.vue index 9f44c8d480..b5dc0caac5 100644 --- a/dbrepo-ui/components/view/ViewToolbar.vue +++ b/dbrepo-ui/components/view/ViewToolbar.vue @@ -19,7 +19,7 @@ <v-btn v-if="canCreatePid" class="mr-2" - :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-content-save-outline' : null" + :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-identifier' : null" variant="flat" color="primary" :text="($vuetify.display.mdAndUp ? $t('toolbars.view.pid.xl') + ' ' : '') + $t('toolbars.view.pid.permanent')" diff --git a/dbrepo-ui/composables/query-service.ts b/dbrepo-ui/composables/query-service.ts index 3d05b9a3cd..5a86c09d1b 100644 --- a/dbrepo-ui/composables/query-service.ts +++ b/dbrepo-ui/composables/query-service.ts @@ -76,11 +76,11 @@ export const useQueryService = (): any => { }) } - async function execute(databaseId: string, data: ExecuteStatementDto, timestamp: Date | null, page: number, size: number): Promise<QueryResultDto> { + async function execute(databaseId: string, subset: SubsetDto, timestamp: Date | null, page: number, size: number): Promise<QueryResultDto> { const axios = useAxiosInstance() console.debug('execute query in database with id', databaseId) return new Promise<QueryResultDto>((resolve, reject) => { - axios.post<QueryResultDto>(`/api/database/${databaseId}/subset`, data, {params: mapFilter(timestamp, page, size), timeout: 600_000}) + axios.post<QueryResultDto>(`/api/database/${databaseId}/subset`, subset, {params: mapFilter(timestamp, page, size), timeout: 600_000}) .then((response) => { console.info('Executed query with id', response.data.id, ' in database with id', databaseId) const result: QueryResultDto = { @@ -135,65 +135,6 @@ export const useQueryService = (): any => { }) } - function build(table: TableDto, columns: ColumnDto[], types: DataTypeDto[], clauses: any[]): QueryBuildResultDto { - var sql = 'SELECT' - for (let i = 0; i < columns.length; i++) { - sql += `${i > 0 ? ',' : ''} \`${columns[i].internal_name}\`` - } - sql += ` FROM \`${table}\`` - if (clauses.length > 0) { - sql += ' WHERE' - for (let i = 0; i < clauses.length; i++) { - const clause = clauses[i] - if (clause.type === 'and' || clause.type === 'or') { - sql += ` ${clause.type.toUpperCase()} ` - continue - } - const filteredColumn = columns.filter(c => c.internal_name === clause.params[0]) - if (filteredColumn.length === 0) { - return { - error: true, - reason: 'column.exists', - column: clause.params[0], - raw: null, - formatted: null - } - } - sql += ` \`${clause.params[0]}\` ${clause.params[1]} ` - const filteredType = types.filter(t => t.value === filteredColumn[0].type) - if (filteredType.length === 0) { - return { - error: true, - reason: 'exists', - column: filteredColumn[0].type, - raw: null, - formatted: null - } - } - if (!filteredType[0].is_buildable) { - return { - error: true, - reason: 'build', - column: filteredColumn[0].type, - raw: null, - formatted: null - } - } - if (filteredType[0].is_quoted) { - sql += `'${clause.params[2]}'` - } else { - sql += `${clause.params[2]}` - } - } - } - return { - error: false, - reason: null, - column: null, - raw: sql - } - } - function mapFilter(timestamp: Date | null, page: number, size: number) { if (!timestamp) { return {page, size} @@ -201,5 +142,5 @@ export const useQueryService = (): any => { return {timestamp, page, size} } - return {findAll, findOne, update, exportCsv, execute, reExecuteData, reExecuteCount, build} + return {findAll, findOne, update, exportCsv, execute, reExecuteData, reExecuteCount} } diff --git a/dbrepo-ui/dto/index.ts b/dbrepo-ui/dto/index.ts index 2f20f17429..e804c3eabf 100644 --- a/dbrepo-ui/dto/index.ts +++ b/dbrepo-ui/dto/index.ts @@ -437,8 +437,9 @@ interface DatabaseModifyImageDto { interface ViewCreateDto { name: string; - query: string; + query: SubsetDto; is_public: boolean; + is_schema_public: boolean; } interface ViewUpdateDto { @@ -477,10 +478,6 @@ interface TableCsvDeleteDto { keys: Map<string, string>; } -interface ExecuteStatementDto { - statement: string; -} - interface ApiErrorDto { status: string; message: string; @@ -599,6 +596,25 @@ interface ImportCsv { line_termination: string; } +interface FilterDto { + type: string; + value: string; + column_id: string; + operator_id: string; +} + +interface OrderDto { + column_id: string; + direction: string; +} + +interface SubsetDto { + table_id: string; + columns: string[]; + filter: FilterDto[] | null; + order: OrderDto[] | null; +} + interface QueryResultDto { id: string | null; result: any; diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json index 1c4298e9b4..1195311a73 100644 --- a/dbrepo-ui/locales/en-US.json +++ b/dbrepo-ui/locales/en-US.json @@ -1017,7 +1017,13 @@ } }, "order": { - "text": "Add Sorting" + "text": "Add Sorting", + "direction": { + "label": "Direction" + }, + "remove": { + "text": "Remove" + } } } } diff --git a/dbrepo-ui/nuxt.config.ts b/dbrepo-ui/nuxt.config.ts index b3da7bd98c..9d6a18146f 100644 --- a/dbrepo-ui/nuxt.config.ts +++ b/dbrepo-ui/nuxt.config.ts @@ -90,7 +90,6 @@ export default defineNuxtConfig({ prefix: '/' }, database: { - unsupported: 'AVG,BIT_AND,BIT_OR,BIT_XOR,COUNT,COUNTDISTINCT,GROUP_CONCAT,JSON_ARRAYAGG,JSON_OBJECTAGG,MAX,MIN,STD,STDDEV,STDDEV_POP,STDDEV_SAMP,SUM,VARIANCE,VAR_POP,VAR_SAMP,--', image: { width: 200, height: 200 diff --git a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue index 5c95a844d7..d0140a6fa1 100644 --- a/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/subset/[subset_id]/info.vue @@ -40,11 +40,11 @@ :resource="identifier" /> </v-list-item> <v-list-item - v-if="subset.creator" + v-if="subset.owner" :title="$t('pages.subset.creator.title')" density="compact"> <UserBadge - :user="subset.creator" + :user="subset.owner" :other-user="cacheUser" /> </v-list-item> <v-list-item diff --git a/helm/dbrepo/files/01-setup-schema.sql b/helm/dbrepo/files/01-setup-schema.sql index 17d303ea7d..2ca58927da 100644 --- a/helm/dbrepo/files/01-setup-schema.sql +++ b/helm/dbrepo/files/01-setup-schema.sql @@ -596,32 +596,14 @@ VALUES ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Equal operator', '=', ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Greater than or equal operator', '>=', 'https://mariadb.com/kb/en/greater-than-or-equal/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Not equal operator', '!=', 'https://mariadb.com/kb/en/not-equal/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Addition operator', '+', - 'https://mariadb.com/kb/en/addition-operator/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Division operator', '/', - 'https://mariadb.com/kb/en/division-operator/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Modulo operator', '%', 'https://mariadb.com/kb/en/modulo-operator/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Multiplication operator', '*', - 'https://mariadb.com/kb/en/multiplication-operator/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Subtraction operator', '-', - 'https://mariadb.com/kb/en/subtraction-operator-/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'LIKE', 'LIKE', 'https://mariadb.com/kb/en/like/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'NOT LIKE', 'NOT LIKE', 'https://mariadb.com/kb/en/not-like/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'IN', 'IN', 'https://mariadb.com/kb/en/in/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'NOT IN', 'NOT IN', 'https://mariadb.com/kb/en/not-in/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'IS', 'IS', 'https://mariadb.com/kb/en/is/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'IS NOT', 'IS NOT', 'https://mariadb.com/kb/en/is-not/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'IS NOT NULL', 'IS NOT NULL', 'https://mariadb.com/kb/en/is-not-null/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'IS NULL', 'IS NULL', 'https://mariadb.com/kb/en/is-null/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'ISNULL', 'ISNULL', 'https://mariadb.com/kb/en/isnull/'), ('d79cb089-363c-488b-9717-649e44d8fcc5', 'REGEXP', 'REGEXP', 'https://mariadb.com/kb/en/regexp/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'NOT REGEXP', 'NOT REGEXP', 'https://mariadb.com/kb/en/not-regexp/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Bitwise AND', '&', 'https://mariadb.com/kb/en/bitwise_and/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Bitwise OR', '|', 'https://mariadb.com/kb/en/bitwise-or/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Bitwise XOR', '^', 'https://mariadb.com/kb/en/bitwise-xor/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Bitwise NOT', '~', 'https://mariadb.com/kb/en/bitwise-not/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Left shift', '<<', 'https://mariadb.com/kb/en/shift-left/'), - ('d79cb089-363c-488b-9717-649e44d8fcc5', 'Right shift', '>>', 'https://mariadb.com/kb/en/shift-right/'); + ('d79cb089-363c-488b-9717-649e44d8fcc5', 'NOT REGEXP', 'NOT REGEXP', 'https://mariadb.com/kb/en/not-regexp/'); INSERT INTO `mdb_ontologies` (prefix, uri, uri_pattern, sparql_endpoint, rdf_path) diff --git a/helm/dbrepo/files/create-event-listener.jar b/helm/dbrepo/files/create-event-listener.jar index 70fca91e2c62b6c899e74332a8e1398e9c8c4b75..a3214b6c85649309e39ba6f970febd743621219e 100644 GIT binary patch delta 692 zcmbQ^KgVAvz?+#xgn@yBgTbpHCTc0u?yVDrl<H6C9WoHu<9^Ei2YZe)uj9$JTiV4O zwJ#p8eVo(f`beQ#_|*ODEoLiLWL0n2`>n71*ygxKQ`M?R>tF22%sF-}NyOcpuW`eJ z&(6ofE-XyF?w9Y=-lu73sq}2^O0Inx+x}#>TgA*ideP8m=|zWyLiJ`LiO0I`JY4ti z!lkzAlDQWv>N{n2tp9asx@WYBUUGNkW82gGIlZjAnY$MMt_n}=o%Zk9?uI&Lk<0R* z{y(XS)HmLyc<ZOnslRplJ}+6fRyT(=h&f!kaj8-LdRCTfRpli0#~KoITT&Tid1|)L zklt|kVYqwK*8X|&))Nd@bf;W;FTa5Ae5};%ecyjG&hNP3yzW^2AK~9ivg<BKbkF*= z=X&Y4v=#C}ZIzdwIhk+0^T;urH>cg9WyzJl@egjWo_+XmkI}pfi>yWClGFXRtdwHZ zka!y4cS^<gifEtk(li6lbk~(3R=%REGK+S7f3#|I@&3#SPXtnBZCuK)UE=0!vfIj{ z{P+bkC?2>N7&sU}@i2KKqY9Hp!Q|_VdQ6@Lli8W%L6ioQ8k1MS<NzjZ5LL@$3Zk|! zd4p6kGM@uc7nysQJPS6*v&>}z(f`<ZI6*Xzz-->lE^?2UK{{5-&IVB$N>eysQ9k*I zk`<Fz!6ao<kRj&Eb|CA@mGwc?3S~2p@(0S+AWBxn6-1?|M1xcwR0#o5;;MNdmF=o= zAnLiQ6Nu7Q3!nT}O>Xi6HFN!n+?)V!MkWzvL`vJe?m?0h0|NsH+cF@)lE!+)$-L^O Qli$g5@u6y(9IWmM0OdLrM*si- delta 667 zcmbQ^KgVAvz?+#xgn@yBgF!zaCQ3p^J8PnlQoV2RVFiJ`>1zKQ?HN>-$<La7wYe;6 z?#gSw+03S8I$3S-e7k@8GO6Qzi{%<xYu{AwN#(pY<wfWI1)rB~wDfirayRE|4ETIg zG2Q#cg-zMZ&6YVIH!`$RN?W_qWd3X2`dbURt}iPr>G8=F30QGtK5ys@<5-J3rZQ2t z3i{U>bDf`9&-~pr{+CT=>Ej}^`KI?aKROV$;-+kX%-!p|xw5x>F~2YQMS7vc{|W!q zpI2=?akDMsd9mjA-+K*~ieGuh8^!3w;F;{rJ}+kViqaQPJ?Hf-PWYmtQ~V;~!S17n z8f5wGt%cUqe))5wagO6!^~H7n8A>bO9lG&t?S1|qogB7LB2U@ZZ}4CB%)EE&iWTRp zL!Ym2`=yvV!#r0pB>1$hT*%b}WgIRZURVFK_QhV1kvpgTm{WIG@I%qEXD-ocCwKTP zzpUfCZqkz=O^+`XC5D%7N~i~W2y9Z?>tt~^diSf-JMWu#6m@LklUwxr(j{)rCc7;x z%8y^jg5rUTfq{bo6c3X(GO94?1x&uqs0X6hndCu~29p|-e!%1aCT$Q^%VY|owlH~v z<QSRHfvAhjJxqE5o8wvLGJ)uSY&@JGnnz$ZFGz8>;_S`KWgjtv*cwVxIABpe`G}Gg zlYYP?WmAwL=E`;;s$5wgM6FOZ11W!?Yz?AhRa`+-ib^y{?x0Eth!R)L15xd&aUkls zsuPIPRtpEIe4!>Yd4Zbw<O_;iYysYkOd`ya7s^WUFhIeQMk~3=y-d=R?=y)_zN{t; J(h{uh2>>c)2Jip? -- GitLab From ecf40416887c370d746932e1c74bea82d2ebd487 Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Sat, 1 Mar 2025 23:39:50 +0100 Subject: [PATCH 05/11] WIP Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- dbrepo-analyse-service/Pipfile.lock | 26 +- .../lib/dbrepo-1.7.0-py3-none-any.whl | Bin 30099 -> 31116 bytes .../lib/dbrepo-1.7.0.tar.gz | Bin 45319 -> 46110 bytes .../target/create-event-listener.jar | Bin 10140 -> 10140 bytes .../at/tuwien/endpoints/SubsetEndpoint.java | 2 +- .../at/tuwien/endpoints/ViewEndpoint.java | 2 +- .../tuwien/validation/EndpointValidator.java | 3 +- .../DatabaseServiceIntegrationTest.java | 4 +- .../service/SubsetServiceIntegrationTest.java | 2 +- .../java/at/tuwien/auth/AuthTokenFilter.java | 7 +- .../auth/BasicAuthenticationProvider.java | 14 +- .../auth/InternalRequestInterceptor.java | 14 +- .../at/tuwien/gateway/KeycloakGateway.java | 5 +- .../gateway/impl/KeycloakGatewayImpl.java | 7 +- .../java/at/tuwien/mapper/DataMapper.java | 4 +- .../java/at/tuwien/mapper/MariaDbMapper.java | 2 +- .../impl/DatabaseServiceMariaDbImpl.java | 4 +- .../impl/SubsetServiceMariaDbImpl.java | 2 +- dbrepo-metadata-db/1_setup-schema.sql | 1 + .../at/tuwien/api/database/DatabaseDto.java | 1 + .../java/at/tuwien/api/database/ViewDto.java | 5 - .../tuwien/api/database/query/FilterDto.java | 4 + .../tuwien/api/database/query/QueryDto.java | 10 +- .../tuwien/api/database/table/TableDto.java | 1 + .../at/tuwien/entities/database/View.java | 4 +- .../tuwien/exception/ViewExistsException.java | 21 ++ .../java/at/tuwien/mapper/MetadataMapper.java | 8 +- .../at/tuwien/endpoints/TableEndpoint.java | 12 +- .../at/tuwien/endpoints/ViewEndpoint.java | 20 +- .../endpoints/ViewEndpointUnitTest.java | 4 +- .../java/at/tuwien/auth/AuthTokenFilter.java | 7 +- .../auth/BasicAuthenticationProvider.java | 14 +- .../gateway/impl/KeycloakGatewayImpl.java | 7 +- .../java/at/tuwien/test/AbstractUnitTest.java | 16 +- .../main/java/at/tuwien/test/BaseTest.java | 229 +++++++++--------- dbrepo-search-service/Pipfile.lock | 2 +- dbrepo-search-service/init/Pipfile.lock | 2 +- .../init/lib/dbrepo-1.7.0-py3-none-any.whl | Bin 30099 -> 31116 bytes .../init/lib/dbrepo-1.7.0.tar.gz | Bin 45319 -> 46110 bytes .../init/tests/test_opensearch_client.py | 4 +- .../lib/dbrepo-1.7.0-py3-none-any.whl | Bin 30099 -> 31116 bytes dbrepo-search-service/lib/dbrepo-1.7.0.tar.gz | Bin 45319 -> 46110 bytes dbrepo-search-service/tests/test_app.py | 2 +- dbrepo-ui/components/subset/Builder.vue | 7 +- dbrepo-ui/locales/en-US.json | 3 +- helm/dbrepo/files/01-setup-schema.sql | 1 + helm/dbrepo/files/create-event-listener.jar | Bin 10140 -> 10140 bytes lib/python/dbrepo/RestClient.py | 25 +- lib/python/dbrepo/api/dto.py | 81 +++++-- lib/python/dbrepo/api/mapper.py | 38 +++ 50 files changed, 364 insertions(+), 263 deletions(-) create mode 100644 dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewExistsException.java create mode 100644 lib/python/dbrepo/api/mapper.py diff --git a/dbrepo-analyse-service/Pipfile.lock b/dbrepo-analyse-service/Pipfile.lock index d107d18f47..0ad21ce99c 100644 --- a/dbrepo-analyse-service/Pipfile.lock +++ b/dbrepo-analyse-service/Pipfile.lock @@ -180,20 +180,20 @@ }, "boto3": { "hashes": [ - "sha256:4320441f904435a1b85e6ecb81793192e522c737cc9ed6566014e29f0a11cb22", - "sha256:96d18f7feb0c1fcb95f8837b74b6c8880e1b4e35ce5f8a8f8cb243a090c278ed" + "sha256:024c37c2f85f4b907f5fc817d0db6fda7fd6ab3c6148ee4ed35fe7cecdf7db0c", + "sha256:1bbf8bbacb3932956b7020d9a2c49d72c64e21bae9397ba6d3aadffab5e192eb" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.37.1" + "version": "==1.37.4" }, "botocore": { "hashes": [ - "sha256:b194db8fb2a0ffba53568c364ae26166e7eec0445496b2ac86a6e142f3dd982f", - "sha256:c1db1bfc5d8c6b3b6d1ca6794f605294b4264e82a7e727b88e0fef9c2b9fbb9c" + "sha256:7e15cd487617440e9eac3144044b6a2bd833d7f3e2bed6a2865693cc11489cc3", + "sha256:89130998c82d53f875a42646b692da507c9871b580fd1aea0f861bf9da36e41a" ], "markers": "python_version >= '3.8'", - "version": "==1.37.1" + "version": "==1.37.4" }, "certifi": { "hashes": [ @@ -421,7 +421,7 @@ }, "dbrepo": { "hashes": [ - "sha256:bf9869660e66e78ea13f2d4428901cdac61e16e4c398251caf808c81da0695ff" + "sha256:83a135d0c054d8420f64029eabd9a630380cce0c5963cdafc661a677593f2553" ], "path": "./lib/dbrepo-1.7.0.tar.gz" }, @@ -1579,19 +1579,19 @@ }, "s3transfer": { "hashes": [ - "sha256:3b39185cb72f5acc77db1a58b6e25b977f28d20496b6e58d6813d75f464d632f", - "sha256:be6ecb39fadd986ef1701097771f87e4d2f821f27f6071c872143884d2950fbc" + "sha256:ca855bdeb885174b5ffa95b9913622459d4ad8e331fc98eb01e6d5eb6a30655d", + "sha256:edae4977e3a122445660c7c114bba949f9d191bae3b34a096f18a1c8c354527a" ], "markers": "python_version >= '3.8'", - "version": "==0.11.2" + "version": "==0.11.3" }, "setuptools": { "hashes": [ - "sha256:3bc32c0b84c643299ca94e77f834730f126efd621de0cc1de64119e0e17dab1f", - "sha256:65fb779a8f28895242923582eadca2337285f0891c2c9e160754df917c3d2530" + "sha256:4880473a969e5f23f2a2be3646b2dfd84af9028716d398e46192f84bc36900d2", + "sha256:558e47c15f1811c1fa7adbd0096669bf76c1d3f433f58324df69f3f5ecac4e8f" ], "markers": "python_version >= '3.9'", - "version": "==75.8.1" + "version": "==75.8.2" }, "six": { "hashes": [ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.7.0-py3-none-any.whl b/dbrepo-analyse-service/lib/dbrepo-1.7.0-py3-none-any.whl index 7bc63ddeff70d4e113017311299aa094e598b5ad..08a42f973e93b8acbd66e40d29ef12ad4fe19ffa 100644 GIT binary patch delta 15567 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 delta 14625 zcmeDA%sBZq;|51|zQfa^qSh@o4o^^JVAwlxvp>5RV?7_=j~l(~_nOSOu>JCbGz-@o z?;hN|;GKEX($Z^g`r(dk4`2K&zkm4qggcWa*#6M{GjFoV*Sw6K2TvR<U)S*a*W1<Q z$~kR6r>Aj#e5UtwV&SZxAC0W7EG%ZU#LaTrpPs|wzv0!xhl+J^=Q=)}OKjELdQN5D z`RRh+0!kj=VZC`~VQu}hJ%1kB%EmnZ`}641;$N3vZ!DH-oAR~caz_60b4R-8WItM> zQoP5Yckb;2#U3TnDupKOENlMf?^S8w^K<8uyx+6YqVtcd%mt+mZh@FUmhk8K@&CTO z`+EEI#LYg57SE4pe0cci&)?gZ<<D!b$T2GWC#OHL<Hs}=&j-SNf*JDzj@6%@^t9zu zhu5Z@*<Q<+6x1|)_21B>@~Nd%<~{4riZ^?l%f27l_<54g-c%27xpSLx3X5uL9;ZGz zx4V9x(LT$Nhh5tw3yvnUu8YccWPh#aSF?CpMNE*k>f}@>!@pDg7~fP{H7_sOpt0Lo zpJU~tmV>2_RKIVje<9#*_*Qrl%jIgF`X`;7A}QbfY)aofPJI-!Z>Pn+9Tm!v#ZHrS zW-xJ2ydoKtX;Ai#;kgm(G%rt!+Iei|f*-d|a`(DkyU%CZlg|;4Z`5$SNU+iql@~lH zUMVl7|0&NXu4CSgzQ+MJ$HnbtT7`!@ill^xJ1bl<y6<DfRx{&p#iQ2E7H8R}d6`M+ z9<9$2iSCm8;+!sPdA`2=s6XGQpob+o>C?TZo}5wq>qlG4VaLQ(ft|`-@-G9Ph^%Q) zdiGdh{zf*Di@UTm?B~YC{P}wK_jHjijd{+T%btqrpF3~2$6j8>(y_~D_4n2#jis@o ztU?pKkBjXpQ&=cq6}c*5lm4a#fjf3P<L>cnt-8!;Y7qIL_2B*&CLS;LELM_GHS|(7 z<ayU@))D`CU8(#L^IsEuFRV7<UC4CdLutX1f-kX;bj4H>C&zHhGL<z<uI5%%&uJAd zeNf!MXIe35;koH07a9d>mVTD1FJ96g{fJd_<4oqmFCS`Wu}(hD-N?jNFxiVojb+k@ zLV?L8JT{E|lQ;5AWm<i9vIno0QrFKTmA<Qw9EjOr;+)-hOaGKs@1sR3_qYz<UlORX zJb9O!{p2aUmW;lW&+$&H_pfKKTRQDU&r=qQyYnNMr!Al5<yx`py3j*T(U(6A6P;Za zxcExe{5fF#@AW!AmIusv+qt%x|Jcj)K0oeHd+y7n{N1ru^AqBO3dQdW)&~gR&d<5= z#c}l^v)<_wyH-!MdYP@HFRsz$^~`A3_Z_b@pR~l4Z2ppW<b39YC6Nb>UA^lg=S7|T zy6mz7Pr;@a3NNZ`FUUj&EnC2|m3tchjY(VP6`YJ+aU(=ADMRx@K~Y$mv3~KT$UQu@ z1%aE-eLAitbI)^nrD+pi#IA^i7x)f8NMkF0cj5aa{STe|^DZxSop#}zQ2r-&R+h^1 z-ZGCSHlK4=ELQOoQj7>{S;`~Ll$`r0wm$W<Om@kQRempTDeQ?44VTW{y6aQZH~SwR z%NVChJ)K}ty~5z$Ui<35o0fcw(sI4;Jjp0p=iK`}Q~d7KPvR6PJS%hePUQaCzfxpF zPg+&a-j%sAq~x+k;hmiid}H_Cn#$*{#^aF0Q)sm7N4?&mn2)Z4$?N`vF;9Hz@52{f zBe`--{ada3J6noB{$D)H>c{WW5`$A`O+`L(&(6B?ylvTaiPZ&X!$R!07MO+p<MK;2 zU&3tdkgc;QKbtRO!nOo~n)f{Z=g*z1-(^$3^VUB0(kHBe7v~qM#a)TadlsN2KDBb= zzwl|3rp0bu#eLd4*~M(zu`}*V&$ljH(iFYo)Ansorql-1Z+$l<H1zj|l)E?EOua*j z`pTrMc8cc9+poC0V>7ph<*ICr^~*lZF*A_g_$}L-*{A-qd&O5D%YT#X*DD`W?K!nl z$@{DR5mwFJr*5!HuIoQ`%w>nnq`40qx{@VRE#=vicASwpZLAUA{5isM>Q|q0)hs>i zw+mkv$)#)G*g2{6hgrS6+e(>#pJaaj`|x6;vEX*5BmQSO1SYRI#dgAS=@qtwIyPSB z9Xv;xwfwhgd}hgEy*TAD`%?9?Ye53e_qXnj{Nh`#moA%}y}g)k*?db|PmUGl$x+_d zHy%B=yjW{*l+OCY35#3}rv1*&_*r74Tzo!kZQBtGXDQQ#f-b4AJN_*6t)KOzE|^E- zLEf{P<5xA-ng0tC=5f5py0(O8%3j_}53D#USFCj~ar=4TP`U9f#!sx=H}<OWH4EM| zW>DPdroLKnn-!;9{B6y|)+ft0Pt{oLWBu#ev<v+gen!VvOPu64)%Ycub)nK@waCGn z!O~$4b5C4S5>Zr*GnzTIeDN&*jZ78wHN3Wr`3waD8(X;Uq;_OIyyfU!D7aku(*)y_ zYD?swP2F)ObFG(L_}_&c@!@sZ&$Zj_gX4BQYu+{Q<NGQT$yrv%W?l*|$#*~Zk?9^^ z&s3&!F%~y@rhDD_pL;mBV?)-H;LlT)&N(P$Fa~@*@yowBxNTypcx&lOWf9J&|E^5w z+f~11mG^?F{vnFDHe7C6F=v9+v~<S9VmasE&v|(B_vgz~XUp7SFui-ai<QgL^3bO_ z)#fVZF5;dA-nUDf|7hzvx>qlL`Xq$I%cIz)Fk%&NcS8hQxX|`r7jz<zfBrk~&V`?x ziPu(fN?!cetJV_5p0epki|zW1V@|V=8yw~2Ze38NUw@XjyVIaAwRcbN_0wlMm9thX zy{9X2c4ok?)(GbZUD<a&e+ulqRHTz!kQ1>tvn?{U<%j0_!yF$}FXc=-a(cF;x4@q_ z$0zG=iQ3c?;p}Jh{#fO^`gKNUMLAm?PrEsqsZ}{vr0LEn?n&HxxOg^i{!`7pd2ubd zCeI#TeY)Yxl>J5Z5k~AA7`SJiTfsAP=XHgHtxwth1_*9Zw7hk%x=(&d_l4cdj}*8i zezXuwy|dDMqx7$kMEye5uaXBu!c~e6MP%eRzu$a*pW>DC4KvP8*fiD6PJiFqrEL={ zdIh+$Gp6XC;EMBjZo2iMK-8_ra*_RQJEy!{mC6_M?oj<stD>XRzm?VR@O`&qTKepR z3dPAf=iMw!V}IoHro>#@@hA9|@AUe-+Q^Nawx_4P=1Sea@pfzL#`s%jPdPd6dbzY! zanq}0eXb2<VxP*&`(DpFVPg~V>wj^6+(|v3gRa(E9}iwD*w@t&chx`Zhp?z|P~nkj zZ!TZCdDW0B|Mc2j!uu}gUvkuPudbhZaZ`DQ8TYTP@5SVv+uU)N`Ov>n-sk=QN#44% z*^7(kow#PW%eF$Pa?MKD4P~+$vsD-F-f=hR3-6kaw0Q@Z{$E>~Wxl87tHzV1w=8)0 zZ+-Dq*7oFYUAL*?(e69O5hi6^o&CBxQb#Vd8U{~&Co<96?ZiE;8_}${w{uOnYL+e_ zQUB|o?75o<$}Nw-zgn&<^zGGchkqqkzO#AMDgByr^J{66NA?q`>{ZNeQ|9`WNC)I< zUB7?(!W&hqs3nKrm40O_HRVfEpS4RWSiUOC;G?0@_hTYuw*|fzx!ze}XkgDCb|HKF z^32%}*0;?)m~kbicV1A{(>KXYTg;Q47rZ}sAt3O5ecMDuja$C|9VYJ5%i(O?x={8Y z({<fMCk;k#Sw=60fU~?4g!G@O@J%nC82o)=E?Yd)E907vnMckqSvHHMul^F(iRY>t zYA5+kN=TI3(G<qtl#%tR<k_wb?B_rKkWZ_uO|CX)6O;;$IW_t8N5{SICiNW8dfZ=S zYP#*v#53|Y6xY<-%~efqf4M$$A6x&8s;%s2H@LbTZkV}O@yri@>E+9o6(n<492Ruc zSa3CCL0NR9E_3!2&9_?j-JODV{0R>BU-zl@b)fl9rq_0F*eVylo*><~Wp{xzYoa=% znT)(}rN#>`M$_9o=bpa^zkOxZmRngdb&X12cb-X%&^DOA_=VvUj{2az6T7yY@@&6W zX!kUHPTa(m-!~nIk5->;@j~fw_{BAw{L9X+c%h!UXXCp!-&Ocp*M`X+-Wa%(kNudz zu~#muR=-eTUR!*lm*LudLBXrpB{i!(1!Z2Y+N>l}ynDkE*Km9By|35h7hihv==sD> z1-H+7r{_Orzj)fZx{dWy@^$uzlKOP_SudjGV>jArFKt_}u-Q567jyTfWq-EyOy?-r zzT|9j>G~`FUbn1WCDhly7s*tQxM>nqKlwt;(}gN`&t=V@c;{nQy!)-jDSAqGZmES^ z-nx6^q}Jk2`*?H7IQIRlxnaNe#IL*jYVMX@UXz!Kvag+{Ho1G>h0AG*y?35FJQNj8 zsy}Hf-XWCz@z<=WGaqx#Jih&i{L7V(vU)2Xp4n6KZRX3nk|$lgHkKHrr*>ymUe)xw zKjqlnO<lJRT-??lu3kF-N2JT0xp}t^yximJQF|)><(?gjoD91sfBNE;n`l^c=|Q}U z49BOt-QpVa?f*?YxT2uznRZzpKfm#UC8{?K-_M-kSI;wrrT6bLw}+dqwgvWVW!e5? z`sZx1umu+qtos|yet33VsM<IAZk%_{LGR)-m7l*Kkb1}bXaDYb(w94Ro;`??d$R15 zLsjC@E$@7!BMi!49=f*CENZ<;v|xn6x`<T|cqXc4?QU&i&93(=>zEh2*ZjM9RMydJ zF<p(HGN&_sQY@cWulz{8+GVrggFTNY89kq}H6>L$-Q?53S?4nN7T@QL%+f#Pom=Kq z9-dp7_{nRo=FH{0*1VlC&1KVxlT04De20I}z4@(5WYL2kjpZNC&GJ7mCH8%_<NT8C zZ>J_ldtdlc<DZcmc=?Tt!b&E&_5>p?P2IE3yKX8zsc6(%-SJFbcA8lI$0wozl?Qf+ zzKg5-rfL6r*_zEqxMnb3JDeHj_n`FOFZ&;E=l<|5wLdTN%IBZ>hqZ;KPp*|X<c6#I zx39Xw;$<c>Z`0i%)ipaNH=lgG;`tNh1&ab&w@ba+kbLZQ$gTSi1Ap`JZ<XKwQfJ}k zcq5Csrh9hy8yj73JmaWX=<V@je?eLO5?{3~IWCW$e*4ra_gm5Yu62^xT;rCo)=5S! z&F>%mm)>(`@&9g{YcY1)&iqQ;wd3}Z`R973G3`^+w7(x6ojx)2sm9I^TuL$l3j?A{ zzulVY(6i_+ho_bz=eo!nSDwm5Z#I0rjNxO(lC-+BR)L;db&u)Q&hEeJwsL>T`s^hg z3G?gsPP~-Llb_9h{BiHJS0TmO7Q4GAz6vVN*5EyR_Wr{u?=;#frhh5r^pw7MUFyxg z!`A~E8WL9SwBOL6J+tD;EpFopzH&#tYcW3eez~qepZ~^f*{gXXNpJTY`I@qe$GAek z#YcaGhxuyeC$6pyF@genv^giPzQcatnXM~3SN5H@H}yiNF2rP*82Fea8O|tlwtjl! zL@%4p)YBqQu1`7i<A<l{O71=1dwMw{URww^7GG`ORggO2n1R?tdl^24BMm3}7B4<E ziJ|<!k*=!8wToll3%0-7)W2=H*s0{-0W*4+d)n;xI-%nCrzFF|e4B*0#`5arhK*d; z`W`Xz_Pm}Svgy>1dcz4#4;ng;m(*rYcm2G<rIjr-<;sTUuqfus2ice;M1O4)KOCTa zY~Lj>L#8*{XQu?!XNsL!xcND^3^$Yg@kiZNui})2)rF7mxw5%%+Z>%7k=OUn7`{B$ zu5iEY@%Fh)w+~OaV$=TaWR&M!b-6cd9D_aVDs<F%mpW~#s$H{*i&dk3fAGiIJ`b;d z_;B<7eEZq<_0Qt%em_3BS>AtM?4S1!FW&1r_4tFe`I3+=bJN1M7%jcEJoL>5#>GN6 z{6&^ki4-bpw|&ntI2rb4>YigV4svTGF1Eejar2;*T0<hY<HF$3^Fn(g{gihp?>roD znZjCkDCBv2#I8?vnUQ&uqwYy2ZTeY1yWBpY=JW;kYYalq3$%4V_J2!j*gQ}209$po z*@0URrH!l}7wzOYDX?JohxpS!I&$--Y*_ck`DUa+`GWUe8}cHaiheo3B_y@#plRux z)&{v|h8Yn#D_<|$vFu#$(a<RV!h;)CU+P|Kk8s<d|8j9=!>xSX&=+&!;^yt&Tl4o_ zZeP7TtJq=h-~E{jo?n@!%Gt4fic98%z!m$GKK60NeomcbX?(-p=_!-q%11lOHlFWE zT*YweW6;|bQ_grVQN293>Dl7K&Mc!(n!cZ2#vQa1WwqvHZpz!p&n>as_|M9g*9UD5 z{m7gyE~~%sLBOX&7k{1lHKVswUvaum2hZV(Cgq1+Y`m96ts8evINE6~!K=VESwdEx zsi$|crK~c~=A*vRiBBeESf;Pkn4BT2#3aKxxkpxBW~I!Umyaam)aNctTN?E>&GV8- zUqH9!!jrKL?e3G0%j)y1E4^OmXZurCjFHdk&N_|Bta8pAKR>>;xs!d@d~$%CD0}de zpGmyu@+arWWk@qbz0_3}-?S`Nr}*T-K1;X9<})f3)ou#ZwLhNxUQStxJ!Grc_hT~e z9G}d-ysG$Qyo$rCN}hIqtNm<~b>t-l_=Tg@ds2_&PLNX6mH*UzaB`@;Wn%i`#5p{( z_g8M=nf*)e&-Uiov47^QlQY|`Gh?^)oi*pr>Tz@4%`1!KcoDpJmG~9Yp!Hirwf1j( zH*v)k*~^91Z=bGNzSpciH#Ye1)=y8kom)5lG`f?zcj-OXYisXqN_h8U+V08k<u&Rz z7G*VA$bFDLTXsjDYoqSgs7cN{n{RdtOxrp4i>p@srx;hUzcc$*K9J`7_w5glivL-L zb7Jjbi(+0o?iUv<FRWQA`tlopv&N&hZ)`feq8EFFZ(rsnSZ^;m<(6ltwolI?!O6Wn z?RPCFtcv>TJ!$?v#trr&tByM_l+wEEzBYBYeSP-IhV90(w|`c8vu@eFB=NTVp)G=} zw@*rXul}-n3a4CF|EkqW{u^0hI3o%_3r~9)uyWc9Z$I`UOWv;cZ`yCA)mVCKU7Ypz zNs~|AxFB`Kxb5S;zBBtChAA7#y<TzdT-nA)xyAYuMI+WPUwlQ_e#-F`3qoZ&6q-dU zL%eM|S9k14sqe@>rFvk`zK!}X+na=z1a_F77KooMSlEC5-}Jqb>T3>Xy=z@7{rhI@ zo#%df+!Eok_62RZC7p41g+p)nq<k*r`1ATuef0i)d7HVGJhe4p{doKBRFm2j8?>(U zZu?*+)*a<`G3#*s@5be;GiPUX>2#dxShZD1^WZjS!R4~E*mSb$dzTh}$ZPen>ermN zcjX3i(QnHRrTMnHeSce*JnfKCf8+bZK^o5YV{2aVMRKKzylq;#VU}53lJYbs$!)S6 z^Kz3luk2~dYu9bs`{<tbJEg~Yk%jj6vY-44TAuo1H}~wjiltF*7xh+LzPjb3kaXbk z)EnCt_`Q~UbSn1K%THFSPaEsa{uJH+_I+*6i(ONTd*&UTouvQokK2*b7rT3nCv9jB zS3j-77}@2O_Uxk9OkpAYvl;clS5LTKS$E?2g0fIf&PIy@zVk=A6)sPVuXJh`eSO(n z@<iUAT&H^mj^eyG-(<Y`W7u%HuZgqYAxWU&TSI1Q-0uY!BC}@+)Li-WAUQ$ZsJ>k| z?aU%w{q~=K9(_(**Z%X*T-Hf~4s+WVUTWMkn{{&Jy4=FKVkr_&oOfUDdR))q?BTFK zTC~d5(KhuyC;z4Oxt)I{cX0Ui3$}Hiiu#gy?}E>s4cjKp@}9Eka<rBNqkZ#X7XkL; z+s`)6dQrJ6X2YH&5B}ZFw_Wx*{_ZV3|8L*y`fY-bpSg+hTNTUm9elX?1fTyL=O|^K z8xId0f1qLYC(C7;xkb*5)mn3moHZ+AQ{GRz&e`(uEbp8<oI2ibxwb8S*4^2BMl9oE z=$>AA{{P?pY_0#{X<8mR|7(3B|NZWS+!s~JJ_&F0?0t^jP!V{)`~Rkg#!m`GomNlD zD|x!Pa(iq2i)7~+;es2TR+X2CE_S@qmCE6#eTBnGX8Y}2;TKg~zAAp{pBOl|<lO0; zcS<k5Ke0TiTfX{g+&jO=N3VZfuGt&3ruXdK$va|$D|kIr#q{1Yyx6on_mR=R%ojN| zbIMe%e=mu%tI17_k+VPHne>cp%Vr(Muj?7VzhAiNH^cw>zvlHT9@`!G?>lG0vA{)# zY97z;|9#Bq*rK`1lxJjEcV(Fd=KVb8Bzkw-*FBx<_kXB!J-*&!!DZ9hQm(shQ!M^< zEdDTWsq>PURgGTSJH->3x&BFi|5)S9RiM1<-R%?2y8~--Mf~}@+8@6S`K)1K9cU|a z->jtHEkN~~+boX^$=yMji|RcuSO?BCJ?8P`yVRQ_P8(eOubkO-uW)Bx@$TXYN~}iq zr;Qc4PpRw(ce;Q4bk4>*tGn6)h37sy`7kE>@tN1lf@Izczqn8vb>O;2_s{LRG1H}v z#nkCf`eF9r=C!{~Z|9vn*~GI~wl~P>Y+0C*)TV#a40GD|7+L@1eLAiG#P9j5MC*B5 zgM+W;D2Pk0Xv)dxt9TxAyiPY@+sa+hPO?Seezo}%1DQnp?4`Il>$mP$p5huU{$<X@ z-IKpa9nzJ0Wwpugi5CB<m+osm>8y6!_UFVxVTGm5NA>Q+q~3}@@R#F~$=vFb;)U)r zEkv(LRu$}y^w9JySp7ev-Mrc5a=dhT-YJH9aj#qnCkOEu9!0;c3Ewvqo;=>PUHR6n zmF9}CO6OQks26dY!Dm|{$GY<CT#Nq|o~kUx2br5gl48meKUdVoM|0&E@jw56>`LnC zuK}CC=!=;jUOxY{{q}jx+uj+iO1&n2o%8Oqs=_6AQ!6w%woCt7^mwyha#+f0%_y0_ z+j_ZVqwD8)M%ql7v#xKk&J4DaSJUNqdppmpPd(^;Ch%O7j!MnXFB4g}Yq~yox_s4- z-A9G2r>n?tP7+p6WjKH1wZC%MMAyHucZKy2-k7H4W9O;v+3-;;^+NnJSG!K_Q`!oC zFH01bF4=czyHKC=O4Sk;myhOe(q(NHir>{S-1n6Czgpv~aJTt2YveX+%BQ`$c+d30 zD%&^J-(QKot@?icvBvDo_1X*6SbRL<6D{^K-{1Vb(!MUpnD^81tLp55y*l1jb&q^E zr)^tqv7`9VV$<Rb(Vu@mto3xYD~_0AGnrRio2h-%WGi*`db2Y<dbbSH|35m+FaCV` zt1R`73rkix<XX#aSG=`<kKO-l<0Uh{n*49e(D$#eD89#&@2D}0$6tP%ltZ_JspI3v zVF%VaO?M4$VViPmPs}Epv)uMiO|`Bsdy^4ochl-zPh6?^+jaM=yYH}CSZu$!#pz{` zx&E4G*9^85%3c<c)>>76FLa;r>}zL5oUf(IFOFHf>r-^EjgWg*Xn2k0tX1oNCM<br z8~!(tTm5>b-v2YXzTq{Jo^Ky@>DOpW?Q+rTkGipAPx;UEyog<oPM;8&yzb*}v3X4{ zCEWgQW+$IT&09OMDCE_r2lL-<YI;>|US#&}!qJ15<v+>2u{!B~^iJ%e{?7WX*NxwY zB)$5f?3HhFuSTqIuF0O1%Dbzl>Pl4k?0Xok&-&iupTmCFoo&aLG})b<&J=CL>VHbB zzBA6V$~$Y_r(*lAv(bwV$DIye)O@SjYfb&rc|tGtef^{I=Tn}3lAG3zjIP5h=bayI ze{pt7x8WY0&uYeI{><I(M`wusDq8R+tp43z?zHz!H+Ls|)0+WiUVQL2)}a3gYw@22 zn*Y|DP4~&0(D2cSrzU*$;>h!+u_mi)In3n!tl7_I#XOapGwt2Xs~WohW?P+`IqPrO z!@Vn?&Wh|!<K8!W)<vzeG3INTgR2VfZV0XT-Zz`+9^W0ausMG%a=Dhg={miv$zb2H z==$ra!3Qp++i*|+QW|5nHSCnVVTGGVqtKfy?(EpT0{3R;RbS3!_uZasS8FDw_)8^J z=lv49Eo*p7*}Jy!<l67L=5}`7irZPY%$5}9di)C6HQ|T)HKP@IpKa_P?$tm4g}d_6 zTn2@TokrgJ@s^TVm)cx~>-Icb>?toSyF;sS&AZHc^PRu9>{kig<<N8ZhnhygY3px~ z{<W(pT$Zw#%)IK!v^^2Ubq`D5%kv(7QM*HP+sWM<{EsaZk~P}lyUjAW|8-Gs!=swc zN7k7_r*icYmxXPb(r|Ik!iux*hyA0T=XK3>`Tq5!Pgnm+m6r?8zAMyhy%w9A-Q&<F zw%eh$w$Xoz)6aU9h_?l|&&}V&y0_|;X06|KE=P`=OKM7IO|Xo2KU&j%_~WG6sxk-e ze3`QG+3b>6fpcnRYn9q*d)P5QcRHk@Iqz`(?Ye001-03^wiAl_V?Me(2yGFad-Ue{ z6-VXP-{`1Hmi`c`*DJK2(Ry3+e7Vj=4J;cHU(9f?50+eL&+|9_aQ$aLzH5=%dpGas z^Ox3r5-w-BeuL-V$9HRY@yKQ*1^PdmvU#OUieTwRo<E#NKYpIH?*5W<4vdU**~Rlb zQaTgrL^q|>KHgKZ+1EaKvWmf8#~QWri!zN_YmePYO198=Y*Mf1yep&o$kwoAqnw_G z)Gcf#aeuQpGhQ-YUdwiP(Ti2}{2f!}IehOtdBybjMf6{{rawx}jJr=H6g=Yb$u#?M zYv<bKFFtMM)5$EpHeXC~qCsABx6r2F0erSnZ)V#$th#hPWPwk(+h^6#;wihiXPsEr z5jDpzyTtqdu}@XMHKPsLtZ(LP8v0#vxhz^OF1<~_Ok~N$kV$XbUfk+<TyJZbT3+91 zKL7e&zt=m<osaaiz5kWcrvCKvjQc!H!8}}1&z81yOwR3VzZibznB_Cot#dm#_RY3D zF)RDEc<nDoORLWn<~IL4+uy#c*r&+9&itxG$Gr5JFSi^ym-Ap#$nvPIyJw4LzMFZZ zs(-F~w^{DJ^Rqw2ZQ^@3dGWK709~7}%GEK=3+q`LyxfFZXKfZ*|MSTV&yo+zEIhvy zT;HQIvon3i#?bF7eA7R#_`{-bwb`~PBJ->HuP^JTc?OslcNO`Hh-4|)&sY3%>dVq8 zdO|CBO)oa(Y22>5lX{AyMYZ*BjML1`4E7ZdxB6@9e7rmB=#+DZ@64B}Ubx`W>NOg6 z1$KMtV;}B5TmM`1)dBs@PMw0sG%C9urbibjzh8XO?BOvz%N-L~Iqf<)zkZ#u@!7}b zIo8rPCkwv5n^|{7QP|%(wQSd^?-S?Lulup-YqEf(>)rXyC)^glZWa*Cp3bhQ#j#!N zYgk{IYlXB+V!6PbFt^KYM*mA6^qx_)4e5RKw?4p|nMH(wfq`SQhwcPsz8lk`qBgXi zwaXA;U=U22{LDb9-d^PLLGzah7i*0S_%|)SGV8~rTSZp6f*hM%ZqIq~s4FPw`*r=w z3XMQ<@1oh~lG4rf`A!}#ey&*Qkv03s!vlreB4?={DP%LTIpS$muvo+I?v!JKyLTM0 zy6@}h<y^E;w6@~pSElKPheDR?sy6CJdroOxb?eFh)3?4<EV$@*)nBvTyIxX<uc=G= zkCB0j@1uB+7l$vFFP>7xRrkcmsJr%%V?OhAH|<FQ<_qFIiwYBq_eH#FYd@IJI?rF6 z`QP#zb!-2vEUg#a@$gtVd;j5skF%$#MKgYVwS2m~UVPhh{o3D8Q+^bg)$FYLTlD+# z`T1?r^WU-mxBv0-vHyM^p+i^2EbC+RK1sj-@%iZAqeodYT2H$QnfFc(x4do7-zfiz zpIs*GliN+jf_}dzZA(_vmNffl|JpdcRb|q%30J#1M0Z(V@={c^Uia)t#FdbYi7ihv zRK4>Y_JpkV&|oiWNC^DBeE-Ke6PEmr5O2@9tK%V?xb9(t+sZg=nVd%!0cwSgnKBFO zKQ#G=?>Y4BX?336hehFBSFe5DA=JO0Rpw3l3z@}9q47&!tlOtLw^zt(+uE+zLBXCH zt<`e`-laIr;&qQb9DnTP(L2jb9__mNGU%DiCSM0z-}pU!mDNJKo~pT))(Whvbw3## zyXf;qPsw9lJNXp98D6ew<+?lVh-Jb1g^V`^@1Lxf@H{nl>oI2azar{U=X<P#c6JHO zujn@TWYgEtG-2K}=Yr|lj$2HoAC2A2=J}eZc<Dul$NP_z+?45+2wqpl8~ea*cTe`3 z6*n)nES>bsbED-%J%RGwOBs(g6bfni*(9zy_AN$2&+U7{%IsCm2hA=m`dfU=*;xMU zzRQgn$D4z%u-0!Wb(WI3y`U)H;^nvH$;{ui6l))B>Fp`<Xel(BvhYRZoV~~X?_~6Q z&hcwo=d_f-BkD!H;)0G|Z{Edjdw->LLhHqyJ-;MkyaU_9S)a}lp407_-ZAB9i?Tbn zyw;lL$moC<&$dq7-Nn#S$!S~Cb5{7z=NrAjf*(&S?#-Xke)0Q}`rX#ElU4IRI_50N zbTW_hy76=4>TI8KcGbC)jUV^UHnv;C@hQJkT~={}UFZ#`-MLol%Xc2Vx%}Gd$|xh7 zegm~R|3ugSW1aT&#>1oC;vckE9ZBjkw&~cu)0jWz#jjl~yG?qv_0DnI)&9~C;hxTv zWBlPxhC<Yj8(a+MvoG==xTjyQd%HyJ{qsfNgPnpO71ZarF`iA*Il}DL^j6hkoy^;w z_kn-Pq>hzDU3lQ|)`Y>=`c=>aEBDC_)AWD1*dJhTT(Ril$0HG3b$j>DJ~7KWd8L;8 z-6bpJBa4%NI)>zDJW)F?vn%7lhpO4RXYG5Ibx+Lj$}G9V@^M+l#<TW0S0_!<*R0>R z;?^FwM2)KRXSB0zgC{6{%oG#*uqpKGq_wX1Unczv`^xhuBm9f7?yBh-n!jdz{_1n3 z>+jMvku$wdGguqnxUe!RI!yDNZuBZ`-6h+e?Ywa3ut45Mh8U#~rDc-k$}Fjh-`i!v zyxM((cI@HJ=H7EHdd;m1v2oS5u@V70d6UFn*RK<MeesIO)Vec|%??Ht=bT+K!|vmc zl-@hBlG|FI8ZKP1acyLr_P0%5&t~r2)O&O76e;sFuCrH7GnMywS>dj<$8YC9k;QfK z$HO<f9KFhGu(sRHlt*J{#ICkWV&3KfRSwB}n2l?WnH8{#%Q|ja-PXbQ@aWMUMvaCW zj~`4}v!FMz{w1GRe*}~1jukA-zjm&=@2*knI+^J!Z;*T=kMxv-G0l_HZm?OHcNDYC z$(^wIB8yk`Q?*O38(3=cCY%>Mu{}`nf$o&D7hMO^J8JqG#rZ3DGTO;IiKe7<926>e zrkGxQKuB>~Kf}*Z$0ip!FB7)8l`A&S{_gOQ^S0Opv1HFSllmuBOiOL29aETpe9B|5 z=|_bEK1@6$V`CrW$6xkg|EdWJ%uLf7tQ=n%ajj5DXxhTEbT8WpU8lJJd`s;&vXtFe zB)hKhwQf-@@4ua{|7*A>Kj2$_VEcjRd_U(j^)hX_$a~`Zf+v%iMJjhPR`GkBXVGEV zc*o%-qj$dJEm^PMVrw=z*RS?*xMk~Q%~(~v#2iBKz6)#?Ua-&omGFhra$k)YxvG~W zG#=H6I>Y4AH9^e7J1~m-i&LP!*axSH;@lMrPjs`2tXRbGc<!T$dhWkvtLFEt)VTlt z!Z-D8fBF7>TK>u7!X@UcmuzpoH+<X8C@B}vCcWT$!<T6fPI6X#;(btG6JX)Ek3H3Q z!e7SJ{fzG`9p3L`?34>wBrOrj?{2#Fq$jVpf^&nBPh(uemt{r2f+wrq&~T9Ub==4B zboMFD5Z`$Ywhph1C+NHUOjB@Pv4|~0$;J1~f%8sZHqV@MRp5E_gPis`XB(yqRL*QH zbH4J9XOUY+U^3?=HI27CJNPEPuD3iPxA0Bz0)dqu`R)lX{C=kKHOJ0*&EH*K*lKGS ziXLo;Yx(kQ!9fmF3-(unLE9bJx{P#=EfT4YV9Gw0ahCOj_~IJwj%9{!msv9m+<5OX zonwBqhxI3)#(iA}Ie|}7x3;a~HK}(vd%x)!|B9dG31`n|oK+3*pYTga#VcTus)JfR z$4(}XWn!KS9NVN~7)#r(gezD(-wapKb<PZTXjE(!jc8pM8V2S*NcTB=xyW(Zw15QB zwy?;POGQqZvsVdTGIsQ4*}8?PbH*f&V`_&tg3MDmSS?Z2&wC|!N#5Zf-dCL@OeQW; z%emmvHEYAuDueicPM*5+4y+G0^>40sk)Cpb&3DNPPU%}gSJ`ToomkHM%O`NY*@=0J z-k4<=xbogo$nCncuJJX`&N$|jwh7q>CMixcb@|4l{9E?KhYq7VjPv_XJeU3Ov!iAo zyRXecwPOp6`Af@qm+DTt=e%G2&3E<}Pq|+`We%`VYUO9BbUD%Q@K8JG2gkO*vqZhU zr`DTJ|9$0Gn1qq}Q8h8GqiT5(Pc*bW@9vv%D*APCb);Qq(8OquoLOvNZTCcdc3K@F z{MlCh?C(8tYd9o7%;it1UX^b9+r)Om!}a?&y-}D{zy9Hc-u&?R<0s#R^PR2>HJz^L z85_7`is$^($Ls%nHhS_qqR^yhkB!Qs8!Ag%{@$N`x;~^JC~m^^NtugwYF?bY+~|tl zf+_DNaGgqYh$&rmc|zg)pxgb=lAhXKtH^k=W>Vd%*?(7gyx97j?dy^I<)@Zje6#ei zncRP`eW#+X@639*<1*9r$S36~Jlh$9PA*GIHI%wtR2LetT&Zd+bC2_*6wch!opw7r z-+!?Eylm<Ymcxn{=hcU-U-7Xe>tFPhz;EUuZkzl3DsE1xQpvJ7eRb=U<x5)&)Z44; zj1{~dE8LT<mRbGs2OsCnOZu)eW$!#GUXc1#xPJB2iumUbmL<i#w7PYIkN0Ev8P&s$ z{(HCZXsDkwD+sJnaKCotcNfc&h2_jUSf|@%O>lg(^Qp&Cj_{TlPq!>KuYdIGkls!s zyY#|aRZF~-9~FeQn!GBtW3-x(`9P{YPNwq7gtCe%v5RH`uAR!uZa<byEpcX^B{%<Z zL;Rx{o2_$;rXA*#sVj|PvG~l<mEHNhBy&p9;p~uOuC|9bRaftpQ+2p_;rStt?~T#T zThx1QKQ=Ku)#Nb8?1=wT<z02h>(19dvRP0icWIvmV`tgQI=<+=3I|_=U%K>W`<70T zJ#|@JY(hCxI45k8T@m<wC;yfADK1}%r`?y<TKM`C^SjP_&96Fty?Rybk?}&!y`6o< zXREx&Ef->+oH((}^8MDF9g4^IiBEfW=Xux3EY{C2EZhALrEh)7mHud%@QR~FI-kov z^n2AmJn(PQ{}mz+WXvibiBER+zUlc#?6&1%i?@H}o^5r0TxV3Hy+2`Y-|MP*Ei3hA z|2t)E&E$DKh&!Qb?IW!TMp3U<`2URK*NOGs>vX4Xk6HPO%{5{B<$?{Y+`eb6y=ncg z`0TIg5ihRndwQkd&wJ^nzgB-@-J&ZGFWd8=rF>4r7QK2;g?07f57r*uR&+Z`YFnF9 z{5{o0tTId3HXm8m6<oggGjpWCuQkR6O&hQII&l9#TmH$Ri|tz>$Mos0rnm2%{wn@P zdWm)CY>uO%UKxqiwZC~e8-p_xr<cdacFk|Pw#ol{)V{^rrsVpmeu?V)Rd~B0_r(6I z=4&U+T=B6*vOCV_L;Y5h_`BQUZfm~_o5xbQ<jG1|rWYk!tpn$@d{9};EBe!E&l+VH z^-G(#a+Dk@+NyZLJDW3c(ZZ*FtJy+Nr(M-snQixO_wjiX5@qJzxp~!ii4xD1MH%UF zU;nILr_R22$Ifu8Rf1D>N-y`k{Gh$!Wc6IrKeHcobtx~saKT(-jy&H#@p_JbpP3Hc zw`MuRksO<U<jI1w{&g8&F3i)aEjSW-R!rjSn%@5Rm%3a3OpQ}E>HHIRqpIfDvEM(| zI<DFw{{N5QDtD2rUe@}f3ZYSXb$(^{g4t!>ELGx@483llKd0_bfnV25H<P6@ofEcC zsk~-<%E`w^b#Y77f)zJb<{$Dqx4D<AKIiIr^CzFw=NP0faBH_ITGqbmrpVGesh2HE zn-BSao_*l3qun#FxDPt(<LXv;R{x6pd-8O|vfJlvI$xhq`eL6i5FY1ZU}SM%;>D_M zyC3Fgm&X@IedFA;;wa;hy<8Wc&q=#G;jt%MSF@$3myhApasefUBJ;&@m$zMeXv4!^ zuy=3$ilY55LKO=a7u{U`RBGC<K7YB;(0Pe=0mhzEMJ`$y+EZJL_^y<`2#>pZV5hU5 zXDq+^)_LDGuWWke_v`&94dH7pPv%N6_Esq>vb0Tl^QzD1{+vD2+S?`9YVzj$<Q7|+ z=e#~wl5={RzElrGlY^H$r$FfSKW>&sv~DkP?cQthtbX;%#M$AjeAb1^Y}#hLM-R=L zG2vVMlA1%cfxP{de_m@pjQch@af_!-_CBNOKaMo}$G&>oW@-A-mTgY)ev7%2tlFhx zj!gR!m;N$~@wv<&_q*IJ*%SV_Pkp}0#+_UDp_JnPz^C>)KSh*&Hb3$`HPKW`|4Haq z-n$)%%{)?{>-PxOZ~ef3EmFHOR^;ErQsLw})w5=W%JGq>tF#%9uD4n;alO)!^{X}> z-*ilFwe*FK`ltu<*F6dB`*HO4X5&cZx{Yk2h0z(0!~#Cc@45KH?OSD)^1IdZO=g~2 zYrFpDnyJRyTH5;`Oj~;N*pzaqmCI%JaOO?uikkL4Vr_o@@@Hq}-0s^`pO>{Uw9JCV zVAtCnjDE@i4q_!N;@vxQ&tA7uuc>!j?DLq-QN{g6R6%L#x?|qiOA;sie&*Zg*vP<k z_0*KjYv#<%ln!s(GtIj2CXc@9GnJ6t#k&1J*T_7Hx_dz^<K3C3r=rdXo}OD{I9vH( zSbCvuV8ZXD+0JLqem7lVS-Fb&o?iV~>+Fr|9`Erzq1?Nf?auaNm-G(&VDsF{dCXP0 zNOxA3-)q70-<;uVO^?spvG>DTrwvOhbM?;tjM#i&QjVw74=r_bM?My_6Sqx`^^U#n zIvw+HYslFN94fq>XMKv7-CS#``!lFwLE}3whK6}8xvuZ6lQSjnY~MLCy>;rHmi630 zdG*f&E<a1sjJqaz+31au;QBXr7BJ<+7WS<*Y!6%P)|YplcZ;L4Pu4#DmjP?cOL@5% zLgr^&YCkaPd`0-VuR(Sq0?rOK_DA>oU75{js3ZRR>5VfxV~<8Y66`&{^k-hKuD49h zxr{}{3=Aijwusv3xUFuT(cbm0o45OD&6Mxq3JnhRTaDi8mHm`@Zmz?#Mb-Q9r-Ut! zCjXYGxqGAIwp`r5RhQ=JtZUdPSrg|L`|<fK)192p4_&B<RdnC}qk}&&Y>O!8ViWl% z+YD!M{dEcmj^oPSb2RM8+C$;F#WpjWy*bV>xb3M`iE&EEjgLEE^je1X;JGE9@`o0( z6<E%HFtxsBnNEGR%}$=nu{CxN|9_5k<l3&BU>v`vx^BDK)6elQt}zRqHtSik^!nNR z+uSneKk@5YUb@(4YTqN}z|f07v;u8kvCgYre9^V##L?yb6E_C&rzAeUB|Y<1zyjuQ z=>yu6{%p<TcVVb?dhgoxQhJNNxxKI3iRS_b*PinGsVno`;Dg+}w)(_ng}kd`q^>6j z*%xll6?@nvEYRS-XXkV2WeO5GCmP;=-J$-k;Q#APm9P5R(l2t>U;KE*cG>lW3xPF{ z9WDf#^n8A1yJ(+l?wPZhk>8bKRiv~$C1$3aRbF!ExY^UrS({9ibXCOsbad}7)KR^A z`tMg^=Bt;?f8U$-nfc&vwSQ0c);~x)y2$2gf3BmD<By{I)?8DcaIcJ?`0mAueOtdd z+xfH~YyN$0D*u%nBdH%r0hw1H{aWcGxb<GZRL#X@6aF;kyiMR-x8&Bo*eB&1o|J!h z{5|2=`{SKI0`ARo%Wc<9TCnxt6xnA#_itg5pLNncr_|_d^`odSH|0~9&Q;xA`mb;I z*?J@OndZ*-HZmzpo}#NzF*UmR;^wnkf8UXcndk7P{{F7lJ2t(QDht0qFZ`r6<AIsh z3x8ZF`sG+uYvK9lNR-1To|5jlpQe;>`^;;!V_YmheU9xpFXk167v_F8+<e)2ZFb1t zv&T*s@5p^w@u0f@fYkKhso!;Pd8Yhq^?4e3rgDD!<9hEUJt6xaihmA`*)myQdf!)z zcVE_a8Ltoi()}W+Z{6zccM~7(RG#>Ihp@_R#?|ldod5elu|_YfX2$k64i7?W7ai^2 zuvVt@uiPbp%J&L6`%jnLdzkq+yzIPOV{ese{GPqiZ&w|DRyk#M{jc(fpGnV+`L%bx z{T-)sKHYl8)(67Xq4m=g4t;yXCbaJAyQD{NuSVCM+TgeU&)3el6<TtaUaiTl*mkXs z+xuN_7k}@(Ir2|doGujCKlLf4?sxEyN13+*UdJr8ykdW$>vv}9v<D`QBJAlLW%nf2 z%d%=Nr>=XmRCV*wn&A0rA*tQRk7ebYVD>tnI`8%K`K+7f{;cY{&+3!tS+5fPjQhC6 z>Mw;N)_2xa-ir9L%V>S?*N|G<fVWTLOfq)cHe7#ro+D(Z*_4OUIW_kmna)}|i}BHk zlM0awf99UdTdJs?r+TQdOughMS4j7p)cs=4&sZLtPStq6`s?3|Mt4tbUl2PjNBa0# z=4Jn@!zJC`tv<Zto$8L3HTx=#7R1$F=8EzttN*AE8mF9WST41h+3f=pGuQN}&0XG0 z`N0gM=o&FWuIW)xXSQ898N<N95Y52AAT!w^TB<(W!`0P?^`IfwVFMo43$e>D+~6_d zUAW{2)6!_orE_I}s4yzCM#>fa-uL}>gI0XSZC~U5mtOoDds-@=wY_kkarM~rpVQuD z%Dl)G`;_zPRo^cCnTM@k1YbLI+_H0)Q`bBf#PBHt$N`DbOm&<L3=HfH3=Ap^3=ESa zip+UI692cqU@l~0U@)FMr%1K_(#gI>0Sv4cYHPV8Y|_N`I<OTwu}P*lJIMX;YHR1| zioZX#Wb%!bJ6_9M?A-Z1?IrJ{XTj^D)=c5J_Ls@urQ9>4@BdTlKc=T+e>*+*(UY2Y z_e6P5Xlgy5)6s{@@+()}vUSR>Rn6e+kiRLPbN}04{x@H~SaIH*lfLlM^@o}fyX%kr zODn#ay48D4z{<Xx!MD7;W^ZQU)kr%gbK~!k6mwJ2na|ASHXB{!op;yb{M6Kx_QpGR z50>&K3ZCARYWtmKLB_<VY3B~7PEN5uP!lcbz1Pe+<Vmv3t&gu9>T*5zUzoi(AvkJ} ze^j`|CaWbJ2Raj;J(9S(qW`gYmuSe@WATeN)|Uty*{xgM@WhNuCg(+r_PINceFfIe z=(c_#=Xlny>0<rXP5UZkKN-xmy~v%*rF~Rae$Lrf7hg*r-4$9<n%uQteM<O^3GcX@ zo-rKV8??dBTyoFe0`|53@6UBC`*<vXLHgB-Te;S2Tf-{d4w)J*v`Vp*@=WtJ*z<$` zn}ze8#mnB+$L)!`bgFZ;{wo(Z*IkiK8qA3Xzm_Jv<eAxFv`22w+ZVFJ(-@e}{$usr zARu-{$vM`4kyXB3dA6%@Y;GF!<sDB9pKEZ+Y&&@6ShSmzw$95fJF0VbtG<4;Y}anV zy}$2?7|i)_?ryew<kbF8JpQv?B-Y6a7_Bz+TU)<6;K|Khw-?s`UXcFr`|8i`S~INA zPTl|6i0MBcACK?tvstm9+1wXxI`#MVl@nzrUCd&;)*W1UimN1sapq<2+zYkSCLFNd zlwS~YNN`&Bzl-O$96Ma<x-xY3vP<F28U7xLo<=j)dR%K-_VvxQCz3O7KTr|Qk1jBI z`d|gi$B)th-i%Bl%;1s!$(g0ClMTvPxDcEACjTi7VmhfaIiSpm>w`W6LrPLnYC-<w z2W1kIx0J~-DowszrYes*H^9Ik$bbM#8Y3o)m)kMDcbUxSCO$c@T#M<C>tsH6DIFw> z!FlA50FPY`KLbOo4g-T6!T^RPji22oJ4Q=RwyqEcW$Vd-71B(z!zVjND^BjO;86f& zBa{q|qE{*ptoKTVAXp)KMue$d(zpSlFu#a*vUVlJRCwlOVPKGjsbpYa*wXkrZ}P$- Yd9eU*RyL409|Ir5HD(5e<%J*~05Q7|5&!@I diff --git a/dbrepo-analyse-service/lib/dbrepo-1.7.0.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.7.0.tar.gz index 2b9ff4cd6fc08ea9eeda814fd64582ec79bae8b3..df984d46425dbda00a0d6d3e2b037a271de0a379 100644 GIT binary patch literal 46110 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 literal 45319 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 D)sD4P diff --git a/dbrepo-auth-service/listeners/target/create-event-listener.jar b/dbrepo-auth-service/listeners/target/create-event-listener.jar index a3214b6c85649309e39ba6f970febd743621219e..a9ba91e5a9968aa8bf870cde04069870cf365960 100644 GIT binary patch delta 646 zcmbQ^KgVAvz?+#xgn@yBgCV3bG3xYJlh}zuO7*_MhZO|&rmOvLv}ah7dF#rZHF8@X zANSdMZ~KOgKEjt8eY5`WHMwe0Ci9g+=S}kc$GYDWd^_j;;I_(_irz5M<I#&#iUL`7 z_9AcOthT(lw6gc*g^e3e^mSBbYn>IZIz7K^#i6Y>eSH%(dzrYV{@A>bi+kC1zH;97 zX=Zm8zwS9yT>s?2+;2<IPYyF*m(X4L*fv`JhLGuQ#;(P;tHKj|r~P|o-CU<EGFkr9 z|0glJ@42=q-umfu>TjLC&r8;=)y-iILJpU1TxwLmu9YQQRXIuhv4(^#?`bA0i683< za}V&f&zI%AW>;1B#^K<CYnRvDw|9`8SDl{o``UZ<KOrr0pFVcf*C)&mIlEpeJ1}tm z_f>jvykDJ98RXyE8sMwDy&@o#`L?2fqGsrSaf>p?;tGrPJ?dLt__a>IF;h5qX1~zV z&pO_dI%h4J@ysAt+|%mXW|@H0%`66I)qcLbcPcdg+}~x6lbolNeh|1jeOjD{z?X%p z5|ZxkLGi%Fz`(%(iigP?8C95r8WShqVAN#}ZcLoa!6XN!HJMbILmCq&2Qq1a={hD8 zFuj$@3#^`r`7D^e#M}*1zd3<r4ilL1pN*Rn%-|KM5d>@LQJe*)HI*iFz@mQg5hW|I zAfvJg*c=OGTad2F70P;GdZn@{SpK0hM4g<93z(m(5(QR&NF^9dOQ`08)pw}Ig6S8k Uj$m3xZ5LSmOSKFz9ir|507g?0k^lez delta 646 zcmbQ^KgVAvz?+#xgn@yBgTbpHCTc0u?yVDrl<H6C9WoHu<9^Ei2YZe)uj9$JTiV4O zwJ#p8eVo(f`beQ#_|*ODEoLiLWL0n2`>n71*ygxKQ`M?R>tF22%sF-}NyOcpuW`eJ z&(6ofE-XyF?w9Y=-lu73sq}2^O0Inx+x}#>TgA*ideP8m=|zWyLiJ`LiO0I`JY4ti z!lkzAlDQWv>N{n2tp9asx@WYBUUGNkW82gGIlZjAnY$MMt_n}=o%Zk9?uI&Lk<0R* z{y(XS)HmLyc<ZOnslRplJ}+6fRyT(=h&f!kaj8-LdRCTfRpli0#~KoITT&Tid1|)L zklt|kVYqwK*8X|&))Nd@bf;W;FTa5Ae5};%ecyjG&hNP3yzW^2AK~9ivg<BKbkF*= z=X&Y4v=#C}ZIzdwIhk+0^T;urH>cg9WyzJl@egjWo_+XmkI}pfi>yWClGFXRtdwHZ zka!y4cS^<gifEtk(li6lbk~(3R=%REGK+S7f3#|I@&3#SPXtnBZCuK)UE=0!vfIj{ z{P+bkC?2>N7&sU}@i2KKqYAS}LCoYEjJnL81u>I3nB>5;CX*_&S3%6=Kqf6PUB_es zrnfSAfz>lHp9RyGn7cvhHz%;nVFEM$vvG5R8N32Df?zE@inGA9rqW~%SkzBGqGSaY zWK=c*n`5DD3(_^YLRk+?uT(Y#%Rf|xsFPE10rOK;qQL48sRV;*3DsP%`VQ4tF#ST+ T5lri-?E<TRsg?nzL)1M00yq#n diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java index d3d461d257..c63ae3f2a2 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java @@ -262,7 +262,7 @@ public class SubsetEndpoint extends RestEndpoint { page, size, timestamp); /* check */ endpointValidator.validateDataParams(page, size); - endpointValidator.validateFilterSubsetParams(data); + endpointValidator.validateSubsetParams(data); /* parameters */ final UUID userId; if (principal != null) { diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 4c4748dc35..b9c00d9bcc 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -156,7 +156,7 @@ public class ViewEndpoint extends RestEndpoint { TableNotFoundException, ImageNotFoundException, QueryMalformedException { log.debug("endpoint create view, databaseId={}, data.name={}", databaseId, data.getName()); /* check */ - endpointValidator.validateFilterSubsetParams(data.getQuery()); + endpointValidator.validateSubsetParams(data.getQuery()); /* create */ final DatabaseDto database = credentialService.getDatabase(databaseId); try { diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java index 5cbbe6bce0..741f82111b 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java @@ -5,6 +5,7 @@ import at.tuwien.api.database.DatabaseAccessDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.query.FilterDto; import at.tuwien.api.database.query.FilterTypeDto; +import at.tuwien.api.database.query.OrderDto; import at.tuwien.api.database.query.SubsetDto; import at.tuwien.config.QueryConfig; import at.tuwien.endpoints.RestEndpoint; @@ -66,7 +67,7 @@ public class EndpointValidator extends RestEndpoint { validateOnlyAccess(database, principal, writeAccessOnly); } - public void validateFilterSubsetParams(SubsetDto subset) throws QueryMalformedException { + public void validateSubsetParams(SubsetDto subset) throws QueryMalformedException { if (subset.getFilter() != null) { final List<FilterDto> filters = subset.getFilter(); FilterTypeDto previous = null; diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java index 183752cb5c..c360bc144c 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java @@ -84,7 +84,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { final ViewDto view0 = response.get(0); assertEquals("not_in_metadata_db2", view0.getName()); assertEquals("not_in_metadata_db2", view0.getInternalName()); - assertEquals(DATABASE_1_ID, view0.getVdbid()); + assertEquals(DATABASE_1_DTO, view0.getDatabase()); assertEquals(USER_1_BRIEF_DTO, view0.getOwner()); assertFalse(view0.getIsInitialView()); assertEquals(DATABASE_1_PUBLIC, view0.getIsPublic()); @@ -438,7 +438,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { final ViewDto response = databaseService.inspectView(DATABASE_1_PRIVILEGED_DTO, "not_in_metadata_db2"); assertEquals("not_in_metadata_db2", response.getInternalName()); assertEquals("not_in_metadata_db2", response.getName()); - assertEquals(DATABASE_1_ID, response.getVdbid()); + assertEquals(DATABASE_1_DTO, response.getDatabase()); assertEquals(USER_1_BRIEF_DTO, response.getOwner()); assertFalse(response.getIsInitialView()); assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java index 6ec99aaa00..8ade3cf923 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java @@ -192,7 +192,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { public void reExecuteCount_malformed_fails() { final QueryDto request = QueryDto.builder() .execution(Instant.now()) - .databaseId(DATABASE_1_ID) + .database(DATABASE_1_DTO) .query("SELECT") // <<< .build(); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java index 3140f77cb5..1e9d1c4bf0 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java @@ -13,6 +13,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; @@ -52,13 +53,13 @@ public class AuthTokenFilter extends OncePerRequestFilter { filterChain.doFilter(request, response); } - public UserDetails verifyJwt(String token) throws ServletException { + public UserDetails verifyJwt(String token) throws BadCredentialsException { final KeyFactory kf; try { kf = KeyFactory.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { log.error("Failed to find RSA algorithm"); - throw new ServletException("Failed to find RSA algorithm", e); + throw new BadCredentialsException("Failed to find RSA algorithm", e); } final X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey)); final RSAPublicKey pubKey; @@ -66,7 +67,7 @@ public class AuthTokenFilter extends OncePerRequestFilter { pubKey = (RSAPublicKey) kf.generatePublic(keySpecX509); } catch (InvalidKeySpecException e) { log.error("Provided public key is invalid"); - throw new ServletException("Provided public key is invalid", e); + throw new BadCredentialsException("Provided public key is invalid", e); } final Algorithm algorithm = Algorithm.RSA256(pubKey, null); final Verification verification = JWT.require(algorithm); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java index 80fdd15f1d..f7f51c0b0d 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java @@ -1,13 +1,10 @@ package at.tuwien.auth; import at.tuwien.api.keycloak.TokenDto; -import at.tuwien.exception.*; import at.tuwien.gateway.KeycloakGateway; -import jakarta.servlet.ServletException; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -29,13 +26,8 @@ public class BasicAuthenticationProvider implements AuthenticationManager { @Override public Authentication authenticate(Authentication auth) throws AuthenticationException { - try { - final TokenDto tokenDto = keycloakGateway.obtainUserToken(auth.getName(), auth.getCredentials().toString()); - final UserDetails userDetails = authTokenFilter.verifyJwt(tokenDto.getAccessToken()); - return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - } catch (ServletException | CredentialsInvalidException | AccountNotSetupException | - AuthServiceConnectionException e) { - throw new BadCredentialsException("Failed to authenticate with authentication service", e); - } + final TokenDto tokenDto = keycloakGateway.obtainUserToken(auth.getName(), auth.getCredentials().toString()); + final UserDetails userDetails = authTokenFilter.verifyJwt(tokenDto.getAccessToken()); + return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java index 20955bcdb3..b0edc929ed 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/auth/InternalRequestInterceptor.java @@ -2,7 +2,6 @@ package at.tuwien.auth; import at.tuwien.api.keycloak.TokenDto; import at.tuwien.config.GatewayConfig; -import at.tuwien.exception.*; import at.tuwien.gateway.KeycloakGateway; import lombok.extern.log4j.Log4j2; import org.springframework.http.HttpHeaders; @@ -31,15 +30,10 @@ public class InternalRequestInterceptor implements ClientHttpRequestInterceptor throws IOException { final HttpHeaders headers = request.getHeaders(); headers.setAccept(List.of(MediaType.APPLICATION_JSON)); - try { - final TokenDto token = keycloakGateway.obtainUserToken(gatewayConfig.getSystemUsername(), - gatewayConfig.getSystemPassword()); - headers.setBearerAuth(token.getAccessToken()); - log.trace("set bearer token for internal user: {}", gatewayConfig.getSystemUsername()); - } catch (AuthServiceConnectionException | CredentialsInvalidException | AccountNotSetupException e) { - log.error("Failed to obtain token for internal user: {}", gatewayConfig.getSystemUsername()); - throw new IOException("Failed to obtain token for internal user", e); - } + final TokenDto token = keycloakGateway.obtainUserToken(gatewayConfig.getSystemUsername(), + gatewayConfig.getSystemPassword()); + headers.setBearerAuth(token.getAccessToken()); + log.trace("set bearer token for internal user: {}", gatewayConfig.getSystemUsername()); return execution.execute(request, body); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java index 9e6a5f56bd..21fbf674db 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java @@ -4,10 +4,11 @@ import at.tuwien.api.keycloak.TokenDto; import at.tuwien.exception.AccountNotSetupException; import at.tuwien.exception.AuthServiceConnectionException; import at.tuwien.exception.CredentialsInvalidException; +import at.tuwien.exception.NotAllowedException; +import org.springframework.security.authentication.BadCredentialsException; public interface KeycloakGateway { - TokenDto obtainUserToken(String username, String password) throws AuthServiceConnectionException, - CredentialsInvalidException, AccountNotSetupException; + TokenDto obtainUserToken(String username, String password) throws BadCredentialsException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java index 62a101c5ce..1e14a4b4ce 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java @@ -4,11 +4,13 @@ import at.tuwien.api.keycloak.TokenDto; import at.tuwien.config.KeycloakConfig; import at.tuwien.gateway.KeycloakGateway; import at.tuwien.mapper.MetadataMapper; +import jakarta.ws.rs.NotAuthorizedException; import lombok.extern.log4j.Log4j2; import org.keycloak.OAuth2Constants; import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.KeycloakBuilder; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.stereotype.Service; @Log4j2 @@ -25,7 +27,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway { } @Override - public TokenDto obtainUserToken(String username, String password) { + public TokenDto obtainUserToken(String username, String password) throws BadCredentialsException { try (Keycloak userKeycloak = KeycloakBuilder.builder() .serverUrl(keycloakConfig.getKeycloakEndpoint()) .realm(keycloakConfig.getRealm()) @@ -37,6 +39,9 @@ public class KeycloakGatewayImpl implements KeycloakGateway { .build()) { return metadataMapper.accessTokenResponseToTokenDto(userKeycloak.tokenManager() .getAccessToken()); + } catch (NotAuthorizedException e) { + log.error("Failed to obtain user token: {}", e.getMessage()); + throw new BadCredentialsException("Failed to obtain user token", e); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java index df65225a3f..5e0ed68455 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java @@ -89,7 +89,7 @@ public interface DataMapper { return ViewDto.builder() .name(resultSet.getString(1)) .internalName(resultSet.getString(1)) - .vdbid(database.getId()) + .database(database) .isInitialView(false) .isPublic(database.getIsPublic()) .isSchemaPublic(database.getIsSchemaPublic()) @@ -179,7 +179,7 @@ public interface DataMapper { .d(resultSet.getString(7) != null ? resultSet.getLong(7) : null) .name(resultSet.getString(10)) .internalName(resultSet.getString(10)) - .databaseId(view.getVdbid()) + .databaseId(view.getDatabase().getId()) .build(); /* fix boolean and set size for others */ if (resultSet.getString(8).equalsIgnoreCase("tinyint(1)")) { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java index 3c87b5a9fa..7f76b40a8a 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java @@ -806,7 +806,7 @@ public interface MariaDbMapper { default SelectConditionStep<Record> subsetDtoToSelectConditions(SelectJoinStep<Record> step, DatabaseDto database, SubsetDto data) throws TableNotFoundException, ImageNotFoundException { - if (data == null || data.getFilter().isEmpty()) { + if (data.getFilter() == null || data.getFilter().isEmpty()) { return step.where(); } SelectConditionStep<Record> conditions = step.where(); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java index b859bcb89e..fc990b0e8e 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java @@ -58,7 +58,7 @@ public class DatabaseServiceMariaDbImpl extends DataConnector implements Databas throw new ViewNotFoundException("Failed to find view in the information schema"); } final ViewDto view = dataMapper.schemaResultSetToView(database, resultSet1); - view.setVdbid(database.getId()); + view.setDatabase(database); view.setOwner(database.getOwner()); /* obtain view columns */ start = System.currentTimeMillis(); @@ -131,7 +131,7 @@ public class DatabaseServiceMariaDbImpl extends DataConnector implements Databas .owner(database.getOwner()) .identifiers(new LinkedList<>()) .isInitialView(false) - .vdbid(database.getId()) + .database(database) .columns(new LinkedList<>()) .build(); try { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java index 869f12bde2..4d3e6df663 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java @@ -147,7 +147,7 @@ public class SubsetServiceMariaDbImpl extends DataConnector implements SubsetSer final QueryDto query = dataMapper.resultSetToQueryDto(resultSet); query.setIdentifiers(metadataServiceGateway.getIdentifiers(database.getId(), queryId)); query.setOwner(database.getOwner()); - query.setDatabaseId(database.getId()); + query.setDatabase(database); return query; } catch (SQLException e) { log.error("Failed to find query with id {}: {}", queryId, e.getMessage()); diff --git a/dbrepo-metadata-db/1_setup-schema.sql b/dbrepo-metadata-db/1_setup-schema.sql index 2ca58927da..12e0f02a16 100644 --- a/dbrepo-metadata-db/1_setup-schema.sql +++ b/dbrepo-metadata-db/1_setup-schema.sql @@ -280,6 +280,7 @@ CREATE TABLE IF NOT EXISTS `mdb_view` last_modified TIMESTAMP, owned_by VARCHAR(36) NOT NULL, PRIMARY KEY (`id`), + UNIQUE (`vdbid`, `internal_name`), FOREIGN KEY (`vdbid`) REFERENCES mdb_databases (`id`), FOREIGN KEY (`owned_by`) REFERENCES mdb_users (`id`) ) WITH SYSTEM VERSIONING; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java index 5ecca1bebc..0c8c85a41c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java @@ -1,6 +1,7 @@ package at.tuwien.api.database; import at.tuwien.api.CacheableDto; +import at.tuwien.api.container.ContainerBriefDto; import at.tuwien.api.container.ContainerDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.identifier.IdentifierDto; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java index 7abd471215..f0f40dd38c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java @@ -28,11 +28,6 @@ public class ViewDto extends CacheableDto { @Schema(example = "787439d0-e85e-400c-a7e6-996a023bfad9") private UUID id; - @NotNull - @JsonProperty("database_id") - @Schema(example = "2b5b2b03-fdd0-40d6-afe0-e5d02fd839e4") - private UUID vdbid; - @NotBlank @Schema(example = "Air Quality") private String name; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java index e78cf6ecb4..2e0c154e03 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java @@ -19,16 +19,20 @@ import java.util.UUID; public class FilterDto { @NotNull + @Schema(example = "where") private FilterTypeDto type; + @NotNull @JsonProperty("column_id") @Schema(example = "14128033-54b5-4818-a489-21b0dded86e2") private UUID columnId; + @NotNull @JsonProperty("operator_id") @Schema(example = ">") private UUID operatorId; + @NotNull @Schema(example = "1") private String value; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java index 3b0f17086a..4a0376e0ea 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java @@ -1,5 +1,6 @@ package at.tuwien.api.database.query; +import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.identifier.IdentifierBriefDto; import at.tuwien.api.user.UserBriefDto; import com.fasterxml.jackson.annotation.JsonFormat; @@ -28,11 +29,6 @@ public class QueryDto { @Schema(example = "83ea2326-f8f6-4263-baf8-cdf88a54efc7") private UUID id; - @NotNull - @JsonProperty("database_id") - @Schema(example = "1a6fb0c0-49c3-4a22-a515-35f7a3dd8e62") - private UUID databaseId; - @NotNull private UserBriefDto owner; @@ -61,6 +57,10 @@ public class QueryDto { @Schema(example = "17e682f060b5f8e47ea04c5c4855908b0a5ad612022260fe50e11ecb0cc0ab76") private String queryHash; + @ToString.Exclude + @EqualsAndHashCode.Exclude + private DatabaseDto database; + @NotNull @JsonProperty("is_persisted") @Schema(example = "true") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java index 3104794394..cb58fab23c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java @@ -2,6 +2,7 @@ package at.tuwien.api.database.table; import at.tuwien.api.CacheableDto; import at.tuwien.api.container.ContainerDto; +import at.tuwien.api.database.DatabaseBriefDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.constraints.ConstraintsDto; diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/View.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/View.java index d2443c7985..8f84a8f066 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/View.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/View.java @@ -25,7 +25,9 @@ import java.util.UUID; @NoArgsConstructor @EqualsAndHashCode @EntityListeners(AuditingEntityListener.class) -@Table(name = "mdb_view") +@Table(name = "mdb_view", uniqueConstraints = { + @UniqueConstraint(columnNames = {"vdbid", "internalName"}) +}) @NamedQueries({ @NamedQuery(name = "View.findAllPublicByDatabaseId", query = "select v from View v where v.database.id = ?1 and v.isPublic = true"), @NamedQuery(name = "View.findAllPublicOrMineByDatabaseId", query = "select v from View v where v.database.id = ?1 and (v.isPublic = true or v.ownedBy = ?2)"), diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewExistsException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewExistsException.java new file mode 100644 index 0000000000..265974db55 --- /dev/null +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewExistsException.java @@ -0,0 +1,21 @@ +package at.tuwien.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.CONFLICT, reason = "error.view.exists") +public class ViewExistsException extends Exception { + + public ViewExistsException(String msg) { + super(msg); + } + + public ViewExistsException(String msg, Throwable thr) { + super(msg + ": " + thr.getLocalizedMessage(), thr); + } + + public ViewExistsException(Throwable thr) { + super(thr); + } + +} diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java index 88eef55622..ad1ef9cf25 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -822,11 +822,6 @@ public interface MetadataMapper { .trim(); } - @Mappings({ - @Mapping(target = "vdbid", source = "database.id"), - @Mapping(target = "database.views", ignore = true), - @Mapping(target = "database.tables", ignore = true) - }) ViewDto viewToViewDto(View data); @Mappings({ @@ -834,6 +829,9 @@ public interface MetadataMapper { }) ViewColumnDto viewColumnToViewColumnDto(ViewColumn data); + @Mappings({ + @Mapping(target = "vdbid", source = "database.id") + }) ViewBriefDto viewToViewBriefDto(View data); @Mappings({ diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index 2f3d38b64c..d2ccae77e6 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -487,14 +487,10 @@ public class TableEndpoint extends AbstractEndpoint { } final TableDto dto = metadataMapper.tableToTableDto(table); final HttpHeaders headers = new HttpHeaders(); - if (isSystem(principal)) { - headers.set("X-Username", table.getDatabase().getContainer().getPrivilegedUsername()); - headers.set("X-Password", table.getDatabase().getContainer().getPrivilegedPassword()); - headers.set("X-Jdbc-Method", table.getDatabase().getContainer().getImage().getJdbcMethod()); - headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Jdbc-Method"); - } else { - removeInternalData(dto.getDatabase().getContainer()); - } + headers.set("X-Username", table.getDatabase().getContainer().getPrivilegedUsername()); + headers.set("X-Password", table.getDatabase().getContainer().getPrivilegedPassword()); + headers.set("X-Jdbc-Method", table.getDatabase().getContainer().getImage().getJdbcMethod()); + headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Jdbc-Method"); return ResponseEntity.ok() .headers(headers) .body(dto); diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 1f4525cd8b..9871fb306c 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -1,7 +1,7 @@ package at.tuwien.endpoints; -import at.tuwien.api.database.ViewBriefDto; import at.tuwien.api.database.CreateViewDto; +import at.tuwien.api.database.ViewBriefDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.ViewUpdateDto; import at.tuwien.api.error.ApiErrorDto; @@ -121,6 +121,11 @@ public class ViewEndpoint extends AbstractEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "409", + description = "View exists with name", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "423", description = "Create view resulted in an invalid query statement", content = {@Content( @@ -141,13 +146,18 @@ public class ViewEndpoint extends AbstractEndpoint { @NotNull @Valid @RequestBody CreateViewDto data, @NotNull Principal principal) throws NotAllowedException, MalformedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, - UserNotFoundException, SearchServiceException, SearchServiceConnectionException, TableNotFoundException, ImageNotFoundException { + UserNotFoundException, SearchServiceException, SearchServiceConnectionException, TableNotFoundException, + ImageNotFoundException, ViewExistsException { log.debug("endpoint create view, databaseId={}, data={}", databaseId, data); final Database database = databaseService.findById(databaseId); if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to create view: not the database owner"); throw new NotAllowedException("Failed to create view: not the database owner"); } + if (database.getViews().stream().anyMatch(v -> v.getInternalName().equals(metadataMapper.nameToInternalName(data.getName())))) { + log.error("Failed to create view: name exists"); + throw new ViewExistsException("Failed to create view: name exists"); + } log.trace("create view for database {}", database); return ResponseEntity.status(HttpStatus.CREATED) .body(metadataMapper.viewToViewBriefDto( @@ -204,13 +214,9 @@ public class ViewEndpoint extends AbstractEndpoint { headers.set("X-Jdbc-Method", view.getDatabase().getContainer().getImage().getJdbcMethod()); headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-View X-Jdbc-Method"); } - final ViewDto dto = metadataMapper.viewToViewDto(view); - if (!isSystem(principal)) { - removeInternalData(dto.getDatabase().getContainer()); - } return ResponseEntity.status(HttpStatus.OK) .headers(headers) - .body(dto); + .body(metadataMapper.viewToViewDto(view)); } @DeleteMapping("/{viewId}") diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java index 94e5a3bf0a..a1c4dabbc8 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java @@ -142,7 +142,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { public void create_succeeds() throws UserNotFoundException, SearchServiceException, MalformedException, NotAllowedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceConnectionException, DataServiceConnectionException, TableNotFoundException, - ImageNotFoundException { + ImageNotFoundException, ViewExistsException { /* test */ create_generic(DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL, USER_1_ID, USER_1, DATABASE_1_USER_1_WRITE_ALL_ACCESS); @@ -483,7 +483,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { DatabaseAccess access) throws MalformedException, DataServiceException, DataServiceConnectionException, NotAllowedException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, TableNotFoundException, - ImageNotFoundException { + ImageNotFoundException, ViewExistsException { final CreateViewDto request = CreateViewDto.builder() .name(VIEW_1_NAME) .query(VIEW_1_SUBSET_DTO) diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java index 35dd5fe2b6..b056eafe17 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java @@ -13,6 +13,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; @@ -52,13 +53,13 @@ public class AuthTokenFilter extends OncePerRequestFilter { filterChain.doFilter(request, response); } - public UserDetails verifyJwt(String token) throws ServletException { + public UserDetails verifyJwt(String token) throws BadCredentialsException { final KeyFactory kf; try { kf = KeyFactory.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { log.error("Failed to find RSA algorithm"); - throw new ServletException("Failed to find RSA algorithm", e); + throw new BadCredentialsException("Failed to find RSA algorithm", e); } final X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey)); final RSAPublicKey pubKey; @@ -66,7 +67,7 @@ public class AuthTokenFilter extends OncePerRequestFilter { pubKey = (RSAPublicKey) kf.generatePublic(keySpecX509); } catch (InvalidKeySpecException e) { log.error("Provided public key is invalid"); - throw new ServletException("Provided public key is invalid", e); + throw new BadCredentialsException("Provided public key is invalid", e); } final Algorithm algorithm = Algorithm.RSA256(pubKey, null); final Verification verification = JWT.require(algorithm); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java index d6535bad49..27a1c271af 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/auth/BasicAuthenticationProvider.java @@ -2,11 +2,9 @@ package at.tuwien.auth; import at.tuwien.api.keycloak.TokenDto; import at.tuwien.gateway.KeycloakGateway; -import jakarta.servlet.ServletException; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -28,13 +26,9 @@ public class BasicAuthenticationProvider implements AuthenticationManager { @Override public Authentication authenticate(Authentication auth) throws AuthenticationException { - try { - final TokenDto tokenDto = keycloakGateway.obtainUserToken(auth.getName(), auth.getCredentials().toString()); - final UserDetails userDetails = authTokenFilter.verifyJwt(tokenDto.getAccessToken()); - log.debug("set basic auth principal: {}", userDetails); - return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - } catch (ServletException e) { - throw new BadCredentialsException("Failed to authenticate with authentication service", e); - } + final TokenDto tokenDto = keycloakGateway.obtainUserToken(auth.getName(), auth.getCredentials().toString()); + final UserDetails userDetails = authTokenFilter.verifyJwt(tokenDto.getAccessToken()); + log.debug("set basic auth principal: {}", userDetails); + return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); } } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java index b67ddfdbfd..4eb96aeee5 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java @@ -8,6 +8,7 @@ import at.tuwien.exception.UserNotFoundException; import at.tuwien.gateway.KeycloakGateway; import at.tuwien.mapper.MetadataMapper; import jakarta.ws.rs.ForbiddenException; +import jakarta.ws.rs.NotAuthorizedException; import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.core.Response; import lombok.extern.log4j.Log4j2; @@ -17,6 +18,7 @@ import org.keycloak.admin.client.KeycloakBuilder; import org.keycloak.admin.client.resource.UserResource; import org.keycloak.representations.idm.UserRepresentation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.stereotype.Service; import java.util.List; @@ -38,7 +40,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway { } @Override - public TokenDto obtainUserToken(String username, String password) { + public TokenDto obtainUserToken(String username, String password) throws BadCredentialsException { try (Keycloak userKeycloak = KeycloakBuilder.builder() .serverUrl(keycloakConfig.getKeycloakEndpoint()) .realm(keycloakConfig.getRealm()) @@ -50,6 +52,9 @@ public class KeycloakGatewayImpl implements KeycloakGateway { .build()) { return metadataMapper.accessTokenResponseToTokenDto(userKeycloak.tokenManager() .getAccessToken()); + } catch (NotAuthorizedException e) { + log.error("Failed to obtain user token: {}", e.getMessage()); + throw new BadCredentialsException("Failed to obtain user token", e); } } diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java index 6dad07c0be..129487d074 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java @@ -43,6 +43,7 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_1.setColumns(new LinkedList<>(TABLE_1_COLUMNS)); TABLE_1.setConstraints(TABLE_1_CONSTRAINTS); VIEW_1_DTO.setIdentifiers(VIEW_1_DTO_IDENTIFIERS); + VIEW_1_DTO.setDatabase(DATABASE_1_DTO); DATABASE_1.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_1, IDENTIFIER_2, IDENTIFIER_3, IDENTIFIER_4))); IDENTIFIER_1.setDatabase(DATABASE_1); IDENTIFIER_2.setDatabase(DATABASE_1); @@ -56,7 +57,7 @@ public abstract class AbstractUnitTest extends BaseTest { DATABASE_1_DTO.setViews(new LinkedList<>(List.of(VIEW_1_DTO, VIEW_2_DTO, VIEW_3_DTO))); TABLE_1_DTO.setColumns(new LinkedList<>(TABLE_1_COLUMNS_DTO)); TABLE_1_DTO.setConstraints(TABLE_1_CONSTRAINTS_DTO); - TABLE_1_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); + TABLE_1_PRIVILEGED_DTO.setDatabase(DATABASE_1_DTO); TABLE_1_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_1_COLUMNS_DTO)); TABLE_1_PRIVILEGED_DTO.setConstraints(TABLE_1_CONSTRAINTS_DTO); TABLE_2.setDatabase(DATABASE_1); @@ -65,7 +66,7 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_2.setConstraints(TABLE_2_CONSTRAINTS); TABLE_2_DTO.setColumns(new LinkedList<>(TABLE_2_COLUMNS_DTO)); TABLE_2_DTO.setConstraints(TABLE_2_CONSTRAINTS_DTO); - TABLE_2_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); + TABLE_2_PRIVILEGED_DTO.setDatabase(DATABASE_1_DTO); TABLE_2_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_2_COLUMNS_DTO)); TABLE_2_PRIVILEGED_DTO.setConstraints(TABLE_2_CONSTRAINTS_DTO); TABLE_3.setDatabase(DATABASE_1); @@ -78,7 +79,7 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_4.setConstraints(TABLE_4_CONSTRAINTS); TABLE_4_DTO.setColumns(TABLE_4_COLUMNS_DTO); TABLE_4_DTO.setConstraints(TABLE_4_CONSTRAINTS_DTO); - TABLE_4_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); + TABLE_4_PRIVILEGED_DTO.setDatabase(DATABASE_1_DTO); TABLE_4_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_4_COLUMNS_DTO)); TABLE_4_PRIVILEGED_DTO.setConstraints(TABLE_4_CONSTRAINTS_DTO); VIEW_1.setDatabase(DATABASE_1); @@ -88,9 +89,11 @@ public abstract class AbstractUnitTest extends BaseTest { VIEW_2.setDatabase(DATABASE_1); VIEW_2.setColumns(new LinkedList<>(VIEW_2_COLUMNS)); VIEW_2_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); + VIEW_2_DTO.setDatabase(DATABASE_1_DTO); VIEW_3.setDatabase(DATABASE_1); VIEW_3.setColumns(new LinkedList<>(VIEW_3_COLUMNS)); VIEW_3_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); + VIEW_3_DTO.setDatabase(DATABASE_1_DTO); IDENTIFIER_1.setDatabase(DATABASE_1); IDENTIFIER_2.setDatabase(DATABASE_1); IDENTIFIER_3.setDatabase(DATABASE_1); @@ -100,6 +103,7 @@ public abstract class AbstractUnitTest extends BaseTest { DATABASE_2.setAccesses(new LinkedList<>(List.of(DATABASE_2_USER_2_WRITE_ALL_ACCESS, DATABASE_2_USER_3_READ_ACCESS))); DATABASE_2.setTables(new LinkedList<>(List.of(TABLE_5, TABLE_6, TABLE_7))); VIEW_4.setColumns(new LinkedList<>(VIEW_4_COLUMNS)); + VIEW_4_DTO.setDatabase(DATABASE_2_DTO); DATABASE_2.setViews(new LinkedList<>(List.of(VIEW_4))); DATABASE_2.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_5))); DATABASE_2_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_2_USER_2_WRITE_ALL_ACCESS_DTO, DATABASE_2_USER_3_READ_ACCESS_DTO))); @@ -115,7 +119,7 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_5.setConstraints(TABLE_5_CONSTRAINTS); TABLE_5_DTO.setColumns(new LinkedList<>(TABLE_5_COLUMNS_DTO)); TABLE_5_DTO.setConstraints(TABLE_5_CONSTRAINTS_DTO); - TABLE_5_PRIVILEGED_DTO.setDatabase(DATABASE_2_PRIVILEGED_DTO); + TABLE_5_PRIVILEGED_DTO.setDatabase(DATABASE_2_DTO); TABLE_6.setDatabase(DATABASE_2); TABLE_6.setColumns(new LinkedList<>(TABLE_6_COLUMNS)); TABLE_6.setConstraints(TABLE_6_CONSTRAINTS); @@ -150,11 +154,13 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_8_DTO.setColumns(new LinkedList<>(TABLE_8_COLUMNS_DTO)); TABLE_8_DTO.setConstraints(TABLE_8_CONSTRAINTS_DTO); TABLE_8_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_8_COLUMNS_DTO)); - TABLE_8_PRIVILEGED_DTO.setDatabase(DATABASE_3_PRIVILEGED_DTO); + TABLE_8_PRIVILEGED_DTO.setDatabase(DATABASE_3_DTO); VIEW_5.setDatabase(DATABASE_3); VIEW_5.setColumns(VIEW_5_COLUMNS); VIEW_5_DTO.setColumns(VIEW_5_COLUMNS_DTO); + VIEW_5_DTO.setDatabase(DATABASE_3_DTO); IDENTIFIER_6.setDatabase(DATABASE_3); + QUERY_9_DTO.setDatabase(DATABASE_3_DTO); /* DATABASE 4 */ DATABASE_4.setSubsets(new LinkedList<>()); DATABASE_4.setAccesses(new LinkedList<>(List.of(DATABASE_4_USER_1_READ_ACCESS, DATABASE_4_USER_2_WRITE_OWN_ACCESS, DATABASE_4_USER_3_WRITE_ALL_ACCESS))); diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java index 193ef916c7..25db961f77 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java @@ -1255,6 +1255,16 @@ public abstract class BaseTest { .lastRetrieved(Instant.now()) .build(); + public static final DatabaseBriefDto DATABASE_3_PRIVILEGED_BRIEF_DTO = DatabaseBriefDto.builder() + .id(DATABASE_3_ID) + .isPublic(DATABASE_3_PUBLIC) + .isSchemaPublic(DATABASE_3_SCHEMA_PUBLIC) + .name(DATABASE_3_NAME) + .internalName(DATABASE_3_INTERNALNAME) + .ownerId(USER_3_ID) + .identifiers(new LinkedList<>()) /* IDENTIFIER_6_DTO */ + .build(); + public static final DatabaseBriefDto DATABASE_3_BRIEF_DTO = DatabaseBriefDto.builder() .id(DATABASE_3_ID) .isPublic(DATABASE_3_PUBLIC) @@ -2555,7 +2565,6 @@ public abstract class BaseTest { public static final QueryDto QUERY_9_DTO = QueryDto.builder() .id(QUERY_9_ID) - .databaseId(DATABASE_3_ID) .query(QUERY_9_STATEMENT) .queryNormalized(QUERY_9_STATEMENT) .resultNumber(QUERY_9_RESULT_NUMBER) @@ -2564,12 +2573,13 @@ public abstract class BaseTest { .execution(QUERY_9_EXECUTION) .isPersisted(QUERY_9_PERSISTED) .owner(USER_1_BRIEF_DTO) + .database(DATABASE_3_DTO) .build(); public static final SubsetDto QUERY_9_SUBSET_DTO = SubsetDto.builder() .tableId(TABLE_9_ID) - .columns(new LinkedList(List.of(COLUMN_9_2_ID, COLUMN_9_3_ID))) - .filter(new LinkedList(List.of(FilterDto.builder() + .columns(new LinkedList<>(List.of(COLUMN_9_2_ID, COLUMN_9_3_ID))) + .filter(new LinkedList<>(List.of(FilterDto.builder() .columnId(COLUMN_9_1_ID) .operatorId(IMAGE_1_OPERATORS_2_ID) .value("Fuji") @@ -2578,7 +2588,6 @@ public abstract class BaseTest { .build(); public static final ViewDto QUERY_9_VIEW_DTO = ViewDto.builder() - .vdbid(DATABASE_4_ID) .query(QUERY_9_STATEMENT) .queryHash(QUERY_9_QUERY_HASH) .owner(USER_1_BRIEF_DTO) @@ -2885,18 +2894,6 @@ public abstract class BaseTest { public static final Instant QUERY_1_EXECUTION = Instant.now(); public static final Boolean QUERY_1_PERSISTED = true; - public static final QueryDto QUERY_1_DTO = QueryDto.builder() - .id(QUERY_1_ID) - .databaseId(DATABASE_1_ID) - .query(QUERY_1_STATEMENT) - .queryHash(QUERY_1_QUERY_HASH) - .resultHash(QUERY_1_RESULT_HASH) - .execution(QUERY_1_EXECUTION) - .owner(USER_1_BRIEF_DTO) - .isPersisted(QUERY_1_PERSISTED) - .resultNumber(3L) - .build(); - public static final SubsetDto QUERY_1_SUBSET_DTO = SubsetDto.builder() .tableId(TABLE_1_ID) .columns(new LinkedList<UUID>(List.of(COLUMN_1_1_ID, COLUMN_1_2_ID, COLUMN_1_3_ID, COLUMN_1_4_ID, COLUMN_1_5_ID))) @@ -2907,7 +2904,6 @@ public abstract class BaseTest { .build(); public static final ViewDto QUERY_1_VIEW_DTO = ViewDto.builder() - .vdbid(DATABASE_1_ID) .query(QUERY_1_STATEMENT) .queryHash(QUERY_1_QUERY_HASH) .owner(USER_1_BRIEF_DTO) @@ -2955,20 +2951,6 @@ public abstract class BaseTest { public static final Instant QUERY_2_LAST_MODIFIED = Instant.ofEpochSecond(1541588352L); public static final Boolean QUERY_2_PERSISTED = false; - public static final QueryDto QUERY_2_DTO = QueryDto.builder() - .id(QUERY_2_ID) - .databaseId(DATABASE_1_ID) - .query(QUERY_2_STATEMENT) - .queryNormalized(QUERY_2_STATEMENT) - .resultNumber(QUERY_2_RESULT_NUMBER) - .resultHash(QUERY_2_RESULT_HASH) - .owner(USER_1_BRIEF_DTO) - .queryHash(QUERY_2_QUERY_HASH) - .execution(QUERY_2_EXECUTION) - .isPersisted(QUERY_2_PERSISTED) - .resultNumber(3L) - .build(); - public static final UUID QUERY_3_ID = UUID.fromString("a9849020-45a7-40a8-9a19-d4ae2b28dd46"); public static final String QUERY_3_STATEMENT = "SELECT `location`, `mintemp` FROM `weather_aus` WHERE `mintemp` > 10"; public static final String QUERY_3_QUERY_HASH = "a3d3dd94ebc7653bb5a3b55dd8ed5e91d3d13c335c6855a1eb4eb7ca14c36ced"; @@ -2979,20 +2961,6 @@ public abstract class BaseTest { public static final Long QUERY_3_RESULT_NUMBER = 2L; public static final Boolean QUERY_3_PERSISTED = true; - public static final QueryDto QUERY_3_DTO = QueryDto.builder() - .id(QUERY_3_ID) - .databaseId(DATABASE_1_ID) - .query(QUERY_3_STATEMENT) - .queryNormalized(QUERY_3_STATEMENT) - .resultNumber(QUERY_3_RESULT_NUMBER) - .resultHash(QUERY_3_RESULT_HASH) - .owner(USER_1_BRIEF_DTO) - .queryHash(QUERY_3_QUERY_HASH) - .execution(QUERY_3_EXECUTION) - .isPersisted(QUERY_3_PERSISTED) - .resultNumber(2L) - .build(); - public static final UUID QUERY_7_ID = UUID.fromString("fe73a325-30a0-444c-b74f-23ce1533e55f"); public static final String QUERY_7_STATEMENT = "SELECT id, date, a.location, lat, lng FROM weather_aus a JOIN weather_location l on a.location = l.location WHERE date = '2008-12-01'"; public static final String QUERY_7_QUERY_HASH = "df7da3801dfb5c191ff6711d79ce6455f3c09ec8323ce1ff7208ab85387263f5"; @@ -3004,20 +2972,6 @@ public abstract class BaseTest { public static final Long QUERY_7_RESULT_ID = 4L; public static final Boolean QUERY_7_PERSISTED = false; - public static final QueryDto QUERY_7_DTO = QueryDto.builder() - .id(QUERY_7_ID) - .databaseId(DATABASE_4_ID) - .query(QUERY_7_STATEMENT) - .queryNormalized(QUERY_7_STATEMENT) - .resultNumber(QUERY_7_RESULT_NUMBER) - .resultHash(QUERY_7_RESULT_HASH) - .owner(USER_1_BRIEF_DTO) - .queryHash(QUERY_7_QUERY_HASH) - .execution(QUERY_7_EXECUTION) - .isPersisted(QUERY_7_PERSISTED) - .resultNumber(2L) - .build(); - public static final UUID QUERY_4_ID = UUID.fromString("18a98197-51ff-4011-9f40-914a11675a6d"); public static final String QUERY_4_STATEMENT = "SELECT `id`, `value` FROM `mfcc`"; public static final String QUERY_4_QUERY_HASH = "df7da3801dfb5c191ff6711d79ce6455f3c09ec8323ce1ff7208ab85387263f5"; @@ -3029,19 +2983,6 @@ public abstract class BaseTest { public static final Long QUERY_4_RESULT_ID = 4L; public static final Boolean QUERY_4_PERSISTED = false; - public static final QueryDto QUERY_4 = QueryDto.builder() - .id(QUERY_4_ID) - .databaseId(DATABASE_3_ID) - .query(QUERY_4_STATEMENT) - .queryHash(QUERY_4_QUERY_HASH) - .resultHash(QUERY_4_RESULT_HASH) - .execution(QUERY_4_EXECUTION) - .isPersisted(QUERY_4_PERSISTED) - .resultNumber(QUERY_4_RESULT_NUMBER) - .owner(USER_3_BRIEF_DTO) - .isPersisted(QUERY_4_PERSISTED) - .build(); - public static final List<Map<String, Object>> QUERY_4_RESULT_DTO = new LinkedList<>(List.of( new HashMap<>() {{ put("id", BigInteger.valueOf(1L)); @@ -3065,7 +3006,6 @@ public abstract class BaseTest { public static final QueryDto QUERY_4_DTO = QueryDto.builder() .id(QUERY_4_ID) - .databaseId(DATABASE_3_ID) .query(QUERY_4_STATEMENT) .queryNormalized(QUERY_4_STATEMENT) .resultNumber(QUERY_4_RESULT_NUMBER) @@ -3074,6 +3014,7 @@ public abstract class BaseTest { .execution(QUERY_4_EXECUTION) .isPersisted(QUERY_4_PERSISTED) .owner(USER_1_BRIEF_DTO) + .database(DATABASE_3_DTO) .build(); public static final UUID QUERY_5_ID = UUID.fromString("1a39f775-e3d5-4865-b4f5-dbbb5693b637"); @@ -3088,7 +3029,6 @@ public abstract class BaseTest { public static final QueryDto QUERY_5_DTO = QueryDto.builder() .id(QUERY_5_ID) - .databaseId(DATABASE_3_ID) .query(QUERY_5_STATEMENT) .queryNormalized(QUERY_5_STATEMENT) .resultNumber(QUERY_5_RESULT_NUMBER) @@ -3097,12 +3037,13 @@ public abstract class BaseTest { .execution(QUERY_5_EXECUTION) .isPersisted(QUERY_5_PERSISTED) .owner(USER_1_BRIEF_DTO) + .database(DATABASE_3_DTO) .build(); public static final SubsetDto QUERY_5_SUBSET_DTO = SubsetDto.builder() .tableId(TABLE_8_ID) - .columns(new LinkedList(List.of(COLUMN_8_1_ID, COLUMN_8_2_ID))) - .filter(new LinkedList(List.of(FilterDto.builder() + .columns(new LinkedList<>(List.of(COLUMN_8_1_ID, COLUMN_8_2_ID))) + .filter(new LinkedList<>(List.of(FilterDto.builder() .columnId(COLUMN_8_2_ID) .operatorId(IMAGE_1_OPERATORS_2_ID) .value("0") @@ -3111,7 +3052,6 @@ public abstract class BaseTest { .build(); public static final ViewDto QUERY_5_VIEW_DTO = ViewDto.builder() - .vdbid(DATABASE_3_ID) .query(QUERY_5_STATEMENT) .queryHash(QUERY_5_QUERY_HASH) .owner(USER_1_BRIEF_DTO) @@ -3144,19 +3084,6 @@ public abstract class BaseTest { public static final Long QUERY_6_RESULT_NUMBER = 1L; public static final Boolean QUERY_6_PERSISTED = true; - public static final QueryDto QUERY_6_DTO = QueryDto.builder() - .id(QUERY_6_ID) - .databaseId(DATABASE_1_ID) - .query(QUERY_6_STATEMENT) - .queryNormalized(QUERY_6_STATEMENT) - .resultNumber(QUERY_6_RESULT_NUMBER) - .resultHash(QUERY_6_RESULT_HASH) - .owner(USER_1_BRIEF_DTO) - .queryHash(QUERY_6_QUERY_HASH) - .execution(QUERY_6_EXECUTION) - .isPersisted(QUERY_6_PERSISTED) - .build(); - public static final List<TableColumn> TABLE_1_COLUMNS = List.of(TableColumn.builder() .id(COLUMN_1_1_ID) .ordinalPosition(0) @@ -4834,20 +4761,6 @@ public abstract class BaseTest { public static final Instant QUERY_8_EXECUTION = Instant.now().minus(1, MINUTES); public static final Boolean QUERY_8_PERSISTED = true; - public static final QueryDto QUERY_8_DTO = QueryDto.builder() - .id(QUERY_8_ID) - .databaseId(DATABASE_2_ID) - .query(QUERY_8_STATEMENT) - .queryNormalized(QUERY_8_STATEMENT) - .resultNumber(QUERY_8_RESULT_NUMBER) - .resultHash(QUERY_8_RESULT_HASH) - .owner(USER_1_BRIEF_DTO) - .queryHash(QUERY_8_QUERY_HASH) - .execution(QUERY_8_EXECUTION) - .isPersisted(QUERY_8_PERSISTED) - .resultNumber(3L) - .build(); - public static final SubsetDto QUERY_8_SUBSET_DTO = SubsetDto.builder() .tableId(TABLE_5_ID) .columns(new LinkedList<>(List.of(COLUMN_5_1_ID, COLUMN_5_2_ID))) @@ -5217,10 +5130,10 @@ public abstract class BaseTest { public static final ViewDto VIEW_1_DTO = ViewDto.builder() .id(VIEW_1_ID) + .database(null) /* DATABASE_1_DTO */ .isInitialView(VIEW_1_INITIAL_VIEW) .name(VIEW_1_NAME) .internalName(VIEW_1_INTERNAL_NAME) - .vdbid(DATABASE_1_ID) .isPublic(VIEW_1_PUBLIC) .isSchemaPublic(VIEW_1_SCHEMA_PUBLIC) .identifiers(null /* VIEW_1_DTO_IDENTIFIERS */) @@ -5235,7 +5148,6 @@ public abstract class BaseTest { .isInitialView(VIEW_1_INITIAL_VIEW) .name(VIEW_1_NAME) .internalName(VIEW_1_INTERNAL_NAME) - .vdbid(DATABASE_1_ID) .isPublic(VIEW_1_PUBLIC) .owner(USER_1_BRIEF_DTO) .query(VIEW_1_QUERY) @@ -5386,11 +5298,10 @@ public abstract class BaseTest { public static final ViewDto VIEW_2_DTO = ViewDto.builder() .id(VIEW_2_ID) - .vdbid(DATABASE_1_ID) + .database(null) /* DATABASE_1_DTO */ .isInitialView(VIEW_2_INITIAL_VIEW) .name(VIEW_2_NAME) .internalName(VIEW_2_INTERNAL_NAME) - .vdbid(DATABASE_1_ID) .isPublic(VIEW_2_PUBLIC) .isSchemaPublic(VIEW_2_SCHEMA_PUBLIC) .columns(VIEW_2_COLUMNS_DTO) @@ -5404,7 +5315,6 @@ public abstract class BaseTest { .isInitialView(VIEW_2_INITIAL_VIEW) .name(VIEW_2_NAME) .internalName(VIEW_2_INTERNAL_NAME) - .vdbid(DATABASE_1_ID) .isPublic(VIEW_2_PUBLIC) .isSchemaPublic(VIEW_2_SCHEMA_PUBLIC) .owner(USER_2_BRIEF_DTO) @@ -5511,7 +5421,6 @@ public abstract class BaseTest { .isInitialView(VIEW_3_INITIAL_VIEW) .name(VIEW_3_NAME) .internalName(VIEW_3_INTERNAL_NAME) - .vdbid(DATABASE_1_ID) .isPublic(VIEW_3_PUBLIC) .isSchemaPublic(VIEW_3_SCHEMA_PUBLIC) .owner(USER_1_BRIEF_DTO) @@ -5568,11 +5477,10 @@ public abstract class BaseTest { public static final ViewDto VIEW_3_DTO = ViewDto.builder() .id(VIEW_3_ID) - .vdbid(DATABASE_1_ID) + .database(null) /* DATABASE_1_DTO */ .isInitialView(VIEW_3_INITIAL_VIEW) .name(VIEW_3_NAME) .internalName(VIEW_3_INTERNAL_NAME) - .vdbid(DATABASE_1_ID) .isPublic(VIEW_3_PUBLIC) .isSchemaPublic(VIEW_3_SCHEMA_PUBLIC) .columns(VIEW_3_COLUMNS_DTO) @@ -5775,11 +5683,10 @@ public abstract class BaseTest { public static final ViewDto VIEW_4_DTO = ViewDto.builder() .id(VIEW_4_ID) - .vdbid(DATABASE_2_ID) + .database(null) /* DATABASE_2_DTO */ .isInitialView(VIEW_4_INITIAL_VIEW) .name(VIEW_4_NAME) .internalName(VIEW_4_INTERNAL_NAME) - .vdbid(DATABASE_2_ID) .isPublic(VIEW_4_PUBLIC) .isSchemaPublic(VIEW_4_SCHEMA_PUBLIC) .query(VIEW_4_QUERY) @@ -5981,11 +5888,10 @@ public abstract class BaseTest { public static final ViewDto VIEW_5_DTO = ViewDto.builder() .id(VIEW_5_ID) - .vdbid(DATABASE_3_ID) + .database(null) /* DATABASE_3_DTO */ .isInitialView(VIEW_5_INITIAL_VIEW) .name(VIEW_5_NAME) .internalName(VIEW_5_INTERNAL_NAME) - .vdbid(DATABASE_3_ID) .isPublic(VIEW_5_PUBLIC) .isSchemaPublic(VIEW_5_SCHEMA_PUBLIC) .query(VIEW_5_QUERY) @@ -7820,6 +7726,16 @@ public abstract class BaseTest { .lastRetrieved(Instant.now()) .build(); + public static final DatabaseBriefDto DATABASE_2_PRIVILEGED_BRIEF_DTO = DatabaseBriefDto.builder() + .id(DATABASE_2_ID) + .isPublic(DATABASE_2_PUBLIC) + .isSchemaPublic(DATABASE_2_SCHEMA_PUBLIC) + .name(DATABASE_2_NAME) + .internalName(DATABASE_2_INTERNALNAME) + .identifiers(new LinkedList<>(List.of(IDENTIFIER_5_BRIEF_DTO))) + .ownerId(USER_2_ID) + .build(); + public static final DatabaseBriefDto DATABASE_2_BRIEF_DTO = DatabaseBriefDto.builder() .id(DATABASE_2_ID) .isPublic(DATABASE_2_PUBLIC) @@ -8454,4 +8370,85 @@ public abstract class BaseTest { .resource(new InputStreamResource(InputStream.nullInputStream())) .build(); + public static final QueryDto QUERY_1_DTO = QueryDto.builder() + .id(QUERY_1_ID) + .query(QUERY_1_STATEMENT) + .queryHash(QUERY_1_QUERY_HASH) + .resultHash(QUERY_1_RESULT_HASH) + .execution(QUERY_1_EXECUTION) + .owner(USER_1_BRIEF_DTO) + .isPersisted(QUERY_1_PERSISTED) + .resultNumber(3L) + .database(DATABASE_1_DTO) + .build(); + + public static final QueryDto QUERY_2_DTO = QueryDto.builder() + .id(QUERY_2_ID) + .query(QUERY_2_STATEMENT) + .queryNormalized(QUERY_2_STATEMENT) + .resultNumber(QUERY_2_RESULT_NUMBER) + .resultHash(QUERY_2_RESULT_HASH) + .owner(USER_1_BRIEF_DTO) + .queryHash(QUERY_2_QUERY_HASH) + .execution(QUERY_2_EXECUTION) + .isPersisted(QUERY_2_PERSISTED) + .resultNumber(3L) + .database(DATABASE_1_DTO) + .build(); + + public static final QueryDto QUERY_3_DTO = QueryDto.builder() + .id(QUERY_3_ID) + .query(QUERY_3_STATEMENT) + .queryNormalized(QUERY_3_STATEMENT) + .resultNumber(QUERY_3_RESULT_NUMBER) + .resultHash(QUERY_3_RESULT_HASH) + .owner(USER_1_BRIEF_DTO) + .queryHash(QUERY_3_QUERY_HASH) + .execution(QUERY_3_EXECUTION) + .isPersisted(QUERY_3_PERSISTED) + .resultNumber(2L) + .database(DATABASE_1_DTO) + .build(); + + public static final QueryDto QUERY_7_DTO = QueryDto.builder() + .id(QUERY_7_ID) + .query(QUERY_7_STATEMENT) + .queryNormalized(QUERY_7_STATEMENT) + .resultNumber(QUERY_7_RESULT_NUMBER) + .resultHash(QUERY_7_RESULT_HASH) + .owner(USER_1_BRIEF_DTO) + .queryHash(QUERY_7_QUERY_HASH) + .execution(QUERY_7_EXECUTION) + .isPersisted(QUERY_7_PERSISTED) + .resultNumber(2L) + .database(DATABASE_4_DTO) + .build(); + + public static final QueryDto QUERY_6_DTO = QueryDto.builder() + .id(QUERY_6_ID) + .query(QUERY_6_STATEMENT) + .queryNormalized(QUERY_6_STATEMENT) + .resultNumber(QUERY_6_RESULT_NUMBER) + .resultHash(QUERY_6_RESULT_HASH) + .owner(USER_1_BRIEF_DTO) + .queryHash(QUERY_6_QUERY_HASH) + .execution(QUERY_6_EXECUTION) + .isPersisted(QUERY_6_PERSISTED) + .database(DATABASE_1_DTO) + .build(); + + public static final QueryDto QUERY_8_DTO = QueryDto.builder() + .id(QUERY_8_ID) + .query(QUERY_8_STATEMENT) + .queryNormalized(QUERY_8_STATEMENT) + .resultNumber(QUERY_8_RESULT_NUMBER) + .resultHash(QUERY_8_RESULT_HASH) + .owner(USER_1_BRIEF_DTO) + .queryHash(QUERY_8_QUERY_HASH) + .execution(QUERY_8_EXECUTION) + .isPersisted(QUERY_8_PERSISTED) + .resultNumber(3L) + .database(DATABASE_2_DTO) + .build(); + } diff --git a/dbrepo-search-service/Pipfile.lock b/dbrepo-search-service/Pipfile.lock index 3a0d92f37c..d3b5ccfbe0 100644 --- a/dbrepo-search-service/Pipfile.lock +++ b/dbrepo-search-service/Pipfile.lock @@ -369,7 +369,7 @@ }, "dbrepo": { "hashes": [ - "sha256:bf9869660e66e78ea13f2d4428901cdac61e16e4c398251caf808c81da0695ff" + "sha256:83a135d0c054d8420f64029eabd9a630380cce0c5963cdafc661a677593f2553" ], "path": "./lib/dbrepo-1.7.0.tar.gz" }, diff --git a/dbrepo-search-service/init/Pipfile.lock b/dbrepo-search-service/init/Pipfile.lock index a4293fcd51..e73e76971a 100644 --- a/dbrepo-search-service/init/Pipfile.lock +++ b/dbrepo-search-service/init/Pipfile.lock @@ -259,7 +259,7 @@ }, "dbrepo": { "hashes": [ - "sha256:bf9869660e66e78ea13f2d4428901cdac61e16e4c398251caf808c81da0695ff" + "sha256:83a135d0c054d8420f64029eabd9a630380cce0c5963cdafc661a677593f2553" ], "path": "./lib/dbrepo-1.7.0.tar.gz" }, diff --git a/dbrepo-search-service/init/lib/dbrepo-1.7.0-py3-none-any.whl b/dbrepo-search-service/init/lib/dbrepo-1.7.0-py3-none-any.whl index 7bc63ddeff70d4e113017311299aa094e598b5ad..08a42f973e93b8acbd66e40d29ef12ad4fe19ffa 100644 GIT binary patch delta 15567 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 delta 14625 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 Yd9eU*RyL409|Ir5HD(5e<%J*~05Q7|5&!@I diff --git a/dbrepo-search-service/init/lib/dbrepo-1.7.0.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.7.0.tar.gz index 2b9ff4cd6fc08ea9eeda814fd64582ec79bae8b3..df984d46425dbda00a0d6d3e2b037a271de0a379 100644 GIT binary patch literal 46110 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 literal 45319 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 D)sD4P diff --git a/dbrepo-search-service/init/tests/test_opensearch_client.py b/dbrepo-search-service/init/tests/test_opensearch_client.py index fe65fd060a..54ef2340ab 100644 --- a/dbrepo-search-service/init/tests/test_opensearch_client.py +++ b/dbrepo-search-service/init/tests/test_opensearch_client.py @@ -22,7 +22,7 @@ req = Database(id="209acf92-5c9b-4633-ad99-113c86f6e948", image=ImageBrief(id="f97791b4-baf4-4b18-8f7d-3084818e6549", name="mariadb", version="11.1.3", - jdbc_method="mariadb")), + default=True)), tables=[Table(id="f94a6164-cad4-4873-a9fd-3fe5313b2e95", database_id="209acf92-5c9b-4633-ad99-113c86f6e948", name="Data", @@ -163,7 +163,7 @@ class OpenSearchClientTest(unittest.TestCase): # test try: - OpenSearchClient().delete_database(database_id=9999) + OpenSearchClient().delete_database(database_id="deadbeef-a5aa-49bb-87e7-6c6271731a1a") except opensearchpy.exceptions.NotFoundError: pass diff --git a/dbrepo-search-service/lib/dbrepo-1.7.0-py3-none-any.whl b/dbrepo-search-service/lib/dbrepo-1.7.0-py3-none-any.whl index 7bc63ddeff70d4e113017311299aa094e598b5ad..08a42f973e93b8acbd66e40d29ef12ad4fe19ffa 100644 GIT binary patch delta 15567 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 delta 14625 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 Yd9eU*RyL409|Ir5HD(5e<%J*~05Q7|5&!@I diff --git a/dbrepo-search-service/lib/dbrepo-1.7.0.tar.gz b/dbrepo-search-service/lib/dbrepo-1.7.0.tar.gz index 2b9ff4cd6fc08ea9eeda814fd64582ec79bae8b3..df984d46425dbda00a0d6d3e2b037a271de0a379 100644 GIT binary patch literal 46110 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 literal 45319 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 D)sD4P diff --git a/dbrepo-search-service/tests/test_app.py b/dbrepo-search-service/tests/test_app.py index f05171299e..d2c8f2bd60 100644 --- a/dbrepo-search-service/tests/test_app.py +++ b/dbrepo-search-service/tests/test_app.py @@ -22,7 +22,7 @@ req = Database(id="209acf92-5c9b-4633-ad99-113c86f6e948", image=ImageBrief(id="f97791b4-baf4-4b18-8f7d-3084818e6549", name="mariadb", version="11.1.3", - jdbc_method="mariadb")), + default=True)), tables=[Table(id="f94a6164-cad4-4873-a9fd-3fe5313b2e95", database_id="209acf92-5c9b-4633-ad99-113c86f6e948", name="Data", diff --git a/dbrepo-ui/components/subset/Builder.vue b/dbrepo-ui/components/subset/Builder.vue index 6f13e07273..60f9568a3f 100644 --- a/dbrepo-ui/components/subset/Builder.vue +++ b/dbrepo-ui/components/subset/Builder.vue @@ -639,7 +639,12 @@ export default { this.$refs.form.validate() }, addFirstSort () { - this.sorts.push({ column_id: this.select[0].id, direction: 'asc' }) + if (this.sorts.length === 0) { + this.columns.filter(c => this.table.constraints.primary_key.map(pk => + pk.column.id).includes(c.id)).forEach(pk => this.sorts.push({ column_id: pk.id, direction: 'asc' })) + } else { + this.sorts.push({ column_id: null, direction: null}) + } this.$refs.form.validate() }, addAnd () { diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json index 1195311a73..55a9692c2d 100644 --- a/dbrepo-ui/locales/en-US.json +++ b/dbrepo-ui/locales/en-US.json @@ -1279,7 +1279,8 @@ "view": { "create": "Failed to create view", "missing": "Failed to find view in metadata database", - "invalid": "Failed to map view query to columns in data service" + "invalid": "Failed to map view query to columns in data service", + "exists": "View with this name exists already" }, "broker": { "connection": "Failed to contact broker service", diff --git a/helm/dbrepo/files/01-setup-schema.sql b/helm/dbrepo/files/01-setup-schema.sql index 2ca58927da..12e0f02a16 100644 --- a/helm/dbrepo/files/01-setup-schema.sql +++ b/helm/dbrepo/files/01-setup-schema.sql @@ -280,6 +280,7 @@ CREATE TABLE IF NOT EXISTS `mdb_view` last_modified TIMESTAMP, owned_by VARCHAR(36) NOT NULL, PRIMARY KEY (`id`), + UNIQUE (`vdbid`, `internal_name`), FOREIGN KEY (`vdbid`) REFERENCES mdb_databases (`id`), FOREIGN KEY (`owned_by`) REFERENCES mdb_users (`id`) ) WITH SYSTEM VERSIONING; diff --git a/helm/dbrepo/files/create-event-listener.jar b/helm/dbrepo/files/create-event-listener.jar index a3214b6c85649309e39ba6f970febd743621219e..a9ba91e5a9968aa8bf870cde04069870cf365960 100644 GIT binary patch delta 646 zcmbQ^KgVAvz?+#xgn@yBgCV3bG3xYJlh}zuO7*_MhZO|&rmOvLv}ah7dF#rZHF8@X zANSdMZ~KOgKEjt8eY5`WHMwe0Ci9g+=S}kc$GYDWd^_j;;I_(_irz5M<I#&#iUL`7 z_9AcOthT(lw6gc*g^e3e^mSBbYn>IZIz7K^#i6Y>eSH%(dzrYV{@A>bi+kC1zH;97 zX=Zm8zwS9yT>s?2+;2<IPYyF*m(X4L*fv`JhLGuQ#;(P;tHKj|r~P|o-CU<EGFkr9 z|0glJ@42=q-umfu>TjLC&r8;=)y-iILJpU1TxwLmu9YQQRXIuhv4(^#?`bA0i683< za}V&f&zI%AW>;1B#^K<CYnRvDw|9`8SDl{o``UZ<KOrr0pFVcf*C)&mIlEpeJ1}tm z_f>jvykDJ98RXyE8sMwDy&@o#`L?2fqGsrSaf>p?;tGrPJ?dLt__a>IF;h5qX1~zV z&pO_dI%h4J@ysAt+|%mXW|@H0%`66I)qcLbcPcdg+}~x6lbolNeh|1jeOjD{z?X%p z5|ZxkLGi%Fz`(%(iigP?8C95r8WShqVAN#}ZcLoa!6XN!HJMbILmCq&2Qq1a={hD8 zFuj$@3#^`r`7D^e#M}*1zd3<r4ilL1pN*Rn%-|KM5d>@LQJe*)HI*iFz@mQg5hW|I zAfvJg*c=OGTad2F70P;GdZn@{SpK0hM4g<93z(m(5(QR&NF^9dOQ`08)pw}Ig6S8k Uj$m3xZ5LSmOSKFz9ir|507g?0k^lez delta 646 zcmbQ^KgVAvz?+#xgn@yBgTbpHCTc0u?yVDrl<H6C9WoHu<9^Ei2YZe)uj9$JTiV4O zwJ#p8eVo(f`beQ#_|*ODEoLiLWL0n2`>n71*ygxKQ`M?R>tF22%sF-}NyOcpuW`eJ z&(6ofE-XyF?w9Y=-lu73sq}2^O0Inx+x}#>TgA*ideP8m=|zWyLiJ`LiO0I`JY4ti z!lkzAlDQWv>N{n2tp9asx@WYBUUGNkW82gGIlZjAnY$MMt_n}=o%Zk9?uI&Lk<0R* z{y(XS)HmLyc<ZOnslRplJ}+6fRyT(=h&f!kaj8-LdRCTfRpli0#~KoITT&Tid1|)L zklt|kVYqwK*8X|&))Nd@bf;W;FTa5Ae5};%ecyjG&hNP3yzW^2AK~9ivg<BKbkF*= z=X&Y4v=#C}ZIzdwIhk+0^T;urH>cg9WyzJl@egjWo_+XmkI}pfi>yWClGFXRtdwHZ zka!y4cS^<gifEtk(li6lbk~(3R=%REGK+S7f3#|I@&3#SPXtnBZCuK)UE=0!vfIj{ z{P+bkC?2>N7&sU}@i2KKqYAS}LCoYEjJnL81u>I3nB>5;CX*_&S3%6=Kqf6PUB_es zrnfSAfz>lHp9RyGn7cvhHz%;nVFEM$vvG5R8N32Df?zE@inGA9rqW~%SkzBGqGSaY zWK=c*n`5DD3(_^YLRk+?uT(Y#%Rf|xsFPE10rOK;qQL48sRV;*3DsP%`VQ4tF#ST+ T5lri-?E<TRsg?nzL)1M00yq#n diff --git a/lib/python/dbrepo/RestClient.py b/lib/python/dbrepo/RestClient.py index 76eeaa18a1..1177372ba1 100644 --- a/lib/python/dbrepo/RestClient.py +++ b/lib/python/dbrepo/RestClient.py @@ -11,6 +11,7 @@ from dbrepo.api.dto import * from dbrepo.api.exceptions import ResponseCodeError, NotExistsError, \ ForbiddenError, MalformedError, NameExistsError, QueryStoreError, ExternalSystemError, \ AuthenticationError, FormatNotAvailable, RequestError, ServiceError, ServiceConnectionError +from dbrepo.api.mapper import query_to_subset logging.basicConfig(format='%(asctime)s %(name)-12s %(levelname)-6s %(message)s', level=logging.INFO, stream=sys.stdout) @@ -720,13 +721,14 @@ class RestClient: raise ResponseCodeError(f'Failed to update view: response code: {response.status_code} is not ' f'202 (ACCEPTED): {response.text}') - def create_view(self, database_id: str, name: str, query: str, is_public: bool, is_schema_public: bool) -> View: + def create_view(self, database_id: str, name: str, query: QueryDefinition, is_public: bool, + is_schema_public: bool) -> ViewBrief: """ Create a view in a database with given database id. :param database_id: The database id. :param name: The name of the created view. - :param query: The query of the created view. + :param query: The query definition of the view. :param is_public: The visibility of the data. If set to true the data will be publicly visible. Optional. Default: `True`. :param is_schema_public: The visibility of the schema metadata. If set to true the schema metadata will be publicly visible. Optional. Default: `True`. @@ -740,13 +742,15 @@ class RestClient: :raises ServiceError: If something went wrong with obtaining the information in the search service. :raises ResponseCodeError: If something went wrong with the retrieval. """ + database = self.get_database(database_id=database_id) + subset = query_to_subset(database, self.get_image(database.container.image.id), query) url = f'/api/database/{database_id}/view' response = self._wrapper(method="post", url=url, force_auth=True, - payload=CreateView(name=name, query=query, is_public=is_public, + payload=CreateView(name=name, query=subset, is_public=is_public, is_schema_public=is_schema_public)) if response.status_code == 201: body = response.json() - return View.model_validate(body) + return ViewBrief.model_validate(body) if response.status_code == 400: raise MalformedError(f'Failed to create view: {response.text}') if response.status_code == 403: @@ -1300,7 +1304,7 @@ class RestClient: raise ResponseCodeError(f'Failed to delete database access: response code: {response.status_code} is not ' f'201 (CREATED): {response.text}') - def create_subset(self, database_id: str, query: str, page: int = 0, size: int = 10, + def create_subset(self, database_id: str, query: QueryDefinition, page: int = 0, size: int = 10, timestamp: datetime.datetime = None) -> DataFrame: """ Executes a SQL query in a database where the current user has at least read access with given database id. The @@ -1308,7 +1312,7 @@ class RestClient: timestamp. :param database_id: The database id. - :param query: The query statement. + :param query: The query definition. :param page: The result pagination number. Optional. Default: `0`. :param size: The result pagination size. Optional. Default: `10`. :param timestamp: The timestamp at which the data validity is set. Optional. Default: <current timestamp>. @@ -1323,15 +1327,17 @@ class RestClient: :raises ServiceError: If something went wrong with obtaining the information in the data service. :raises ResponseCodeError: If something went wrong with the retrieval. """ - url = f'/api/database/{database_id}/subset' + database = self.get_database(database_id=database_id) + subset = query_to_subset(database, self.get_image(database.container.image.id), query) params = [] if page is not None and size is not None: params.append(('page', page)) params.append(('size', size)) if timestamp is not None: params.append(('timestamp', timestamp.strftime("%Y-%m-%dT%H:%M:%SZ"))) + url = f'/api/database/{database_id}/subset' response = self._wrapper(method="post", url=url, headers={"Accept": "application/json"}, params=params, - payload=ExecuteQuery(statement=query)) + payload=subset) if response.status_code == 201: logging.info(f'Created subset with id: {response.headers["X-Id"]}') return DataFrame.from_records(response.json()) @@ -1710,7 +1716,7 @@ class RestClient: def get_identifiers(self, database_id: str = None, subset_id: str = None, view_id: str = None, table_id: str = None, type: IdentifierType = None, status: IdentifierStatusType = None) -> List[ - Identifier]: + Identifier]: """ Get list of identifiers, filter by the remaining optional arguments. @@ -1829,7 +1835,6 @@ class RestClient: raise ResponseCodeError(f'Failed to get messages: response code: {response.status_code} is not ' f'200 (OK): {response.text}') - def update_table_column(self, database_id: str, table_id: str, column_id: str, concept_uri: str = None, unit_uri: str = None) -> Column: """ diff --git a/lib/python/dbrepo/api/dto.py b/lib/python/dbrepo/api/dto.py index 203a80f5c3..53b61015ff 100644 --- a/lib/python/dbrepo/api/dto.py +++ b/lib/python/dbrepo/api/dto.py @@ -21,13 +21,8 @@ class Operator(BaseModel): class Image(BaseModel): id: str - registry: str name: str version: str - dialect: str - driver_class: str - jdbc_method: str - default_port: int default: bool data_types: List[DataType] = field(default_factory=list) operators: List[Operator] = field(default_factory=list) @@ -711,13 +706,13 @@ class IdentifierBrief(BaseModel): class View(BaseModel): id: str - database_id: str name: str query: str query_hash: str owner: UserBrief internal_name: str is_public: bool + database: DatabaseBrief is_schema_public: bool initial_view: bool columns: List[ViewColumn] @@ -726,7 +721,7 @@ class View(BaseModel): class CreateView(BaseModel): name: str - query: str + query: Subset is_public: bool is_schema_public: bool @@ -792,8 +787,59 @@ class UnitBrief(BaseModel): description: Optional[str] = None -class ExecuteQuery(BaseModel): - statement: str +class FilterType(str, Enum): + """ + Enumeration of filter types. + """ + WHERE = "where" + OR = "or" + AND = "and" + + +class OrderType(str, Enum): + """ + Enumeration of order types. + """ + ASC = "asc" + DESC = "desc" + + +class Filter(BaseModel): + type: FilterType + column_id: str + operator_id: str + value: str + + +class FilterDefinition(BaseModel): + type: FilterType + column: str + operator: str + value: str + + +class Order(BaseModel): + column_id: str + direction: Optional[OrderType] = None + + +class OrderDefinition(BaseModel): + column: str + direction: Optional[OrderType] = None + + +class Subset(BaseModel): + table_id: str + columns: List[str] + filter: Optional[List[Filter]] = None + order: Optional[List[Order]] = None + + +class QueryDefinition(BaseModel): + table: str + columns: List[str] + filter: Optional[List[FilterDefinition]] = None + order: Optional[List[OrderDefinition]] = None class TitleType(str, Enum): @@ -929,23 +975,6 @@ class IdentifierStatusType(str, Enum): """The identifier is a draft and can still be edited.""" -class IdentifierType(str, Enum): - """ - Enumeration of identifier types. - """ - TABLE = "table" - """The identifier identifies a table.""" - - DATABASE = "database" - """The identifier identifies a database.""" - - VIEW = "view" - """The identifier identifies a view.""" - - SUBSET = "subset" - """The identifier identifies a subset.""" - - class Query(BaseModel): id: str owner: UserBrief diff --git a/lib/python/dbrepo/api/mapper.py b/lib/python/dbrepo/api/mapper.py new file mode 100644 index 0000000000..7ab697a81c --- /dev/null +++ b/lib/python/dbrepo/api/mapper.py @@ -0,0 +1,38 @@ +from dbrepo.api.dto import Subset, QueryDefinition, Database, Table, Image, Filter, Order +from dbrepo.api.exceptions import MalformedError + + +def query_to_subset(database: Database, image: Image, query: QueryDefinition) -> Subset: + if len(query.columns) < 1: + raise MalformedError(f'Failed to create view: no columns selected') + tables: [Table] = [table for table in database.tables if table.internal_name == query.table] + if len(tables) != 1: + raise MalformedError(f'Failed to create view: table name not found in database') + filtered_column_ids: [str] = [column.id for column in tables[0].columns if + column.internal_name in query.columns] + if len(filtered_column_ids) != len(query.columns): + raise MalformedError(f'Failed to create view: not all columns found in database') + filter = [] + if query.filter is not None: + for filter in query.filter: + # column_id + filter_column_ids: [str] = [column.id for column in tables[0].columns if + column.internal_name == filter.column] + if len(filter_column_ids) != 1: + raise MalformedError(f'Failed to create view: filtered column name not found in database') + # operator_id + filter_ops_ids: [str] = [op for op in image.operators if op.value == filter.operator] + if len(filter_ops_ids) != 1: + raise MalformedError(f'Failed to create view: filter operator not found in image') + filter.append(Filter(type=filter.type, column_id=filter_column_ids[0].id, operator_id=filter_ops_ids[0].id, + value=filter.value)) + order = None + if query.order is not None: + for order in query.order: + # column_id + order_column_ids: [str] = [column.id for column in tables[0].columns if + column.internal_name == order.column] + if len(order_column_ids) != 1: + raise MalformedError(f'Failed to create view: order column name not found in database') + order.append(Order(column_id=order_column_ids[0].id, direction=order.direction)) + return Subset(table_id=tables[0].id, columns=filtered_column_ids, filter=filter, order=order) -- GitLab From 45ec28021fe8ed4e29a30a352194008584e16e8e Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Sun, 2 Mar 2025 12:53:15 +0100 Subject: [PATCH 06/11] WIP Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- .../target/create-event-listener.jar | Bin 10140 -> 10140 bytes .../at/tuwien/endpoints/AccessEndpoint.java | 20 +- .../at/tuwien/endpoints/DatabaseEndpoint.java | 14 +- .../at/tuwien/endpoints/SubsetEndpoint.java | 24 +- .../at/tuwien/endpoints/TableEndpoint.java | 103 +++-- .../at/tuwien/endpoints/ViewEndpoint.java | 41 +- .../tuwien/validation/EndpointValidator.java | 7 +- .../endpoint/AccessEndpointUnitTest.java | 4 +- .../endpoint/DatabaseEndpointUnitTest.java | 4 +- .../endpoint/SubsetEndpointUnitTest.java | 6 +- .../endpoint/TableEndpointUnitTest.java | 397 ++++++++++++------ .../tuwien/endpoint/ViewEndpointUnitTest.java | 62 +-- .../MetadataServiceGatewayUnitTest.java | 23 +- .../DefaultListenerIntegrationTest.java | 11 +- .../listener/DefaultListenerUnitTest.java | 15 +- .../service/CredentialServiceUnitTest.java | 34 +- .../DatabaseServiceIntegrationTest.java | 18 +- .../service/QueueServiceIntegrationTest.java | 29 +- .../service/SubsetServiceIntegrationTest.java | 2 +- .../service/TableServiceIntegrationTest.java | 40 +- .../service/ViewServiceIntegrationTest.java | 2 +- .../impl/MetadataServiceGatewayImpl.java | 20 - .../at/tuwien/listener/DefaultListener.java | 17 +- .../java/at/tuwien/mapper/DataMapper.java | 21 +- .../java/at/tuwien/mapper/MariaDbMapper.java | 39 +- .../java/at/tuwien/mapper/MetadataMapper.java | 4 - ...edentialService.java => CacheService.java} | 2 +- .../java/at/tuwien/service/QueueService.java | 4 +- .../java/at/tuwien/service/TableService.java | 19 +- .../java/at/tuwien/service/ViewService.java | 7 +- ...ServiceImpl.java => CacheServiceImpl.java} | 12 +- .../at/tuwien/service/impl/DataConnector.java | 14 - .../impl/DatabaseServiceMariaDbImpl.java | 11 +- .../impl/QueueServiceRabbitMqImpl.java | 8 +- .../impl/SubsetServiceMariaDbImpl.java | 2 +- .../service/impl/TableServiceMariaDbImpl.java | 97 +++-- .../service/impl/ViewServiceMariaDbImpl.java | 22 +- .../at/tuwien/api/container/ContainerDto.java | 11 +- .../java/at/tuwien/api/database/ViewDto.java | 9 +- .../tuwien/api/database/query/QueryDto.java | 9 +- .../tuwien/api/database/table/TableDto.java | 8 +- .../java/at/tuwien/mapper/MetadataMapper.java | 17 +- .../at/tuwien/endpoints/TableEndpoint.java | 11 - .../at/tuwien/endpoints/ViewEndpoint.java | 23 - .../java/at/tuwien/test/AbstractUnitTest.java | 21 - .../main/java/at/tuwien/test/BaseTest.java | 208 +-------- helm/dbrepo/files/create-event-listener.jar | Bin 10140 -> 10140 bytes lib/python/dbrepo/api/dto.py | 4 +- lib/python/dbrepo/api/mapper.py | 12 +- lib/python/tests/test_unit_query.py | 208 +++++++-- lib/python/tests/test_unit_view.py | 253 ++++++++--- 51 files changed, 1076 insertions(+), 873 deletions(-) rename dbrepo-data-service/services/src/main/java/at/tuwien/service/{CredentialService.java => CacheService.java} (99%) rename dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/{CredentialServiceImpl.java => CacheServiceImpl.java} (91%) diff --git a/dbrepo-auth-service/listeners/target/create-event-listener.jar b/dbrepo-auth-service/listeners/target/create-event-listener.jar index a9ba91e5a9968aa8bf870cde04069870cf365960..1d72200c19c7b9fb124773e3ffc0249d1b535e2f 100644 GIT binary patch delta 712 zcmbQ^KgVAvz?+#xgn@yBgMlw8DJoWZ(WZ$)O7#bW4jBmSEnoJ3g1iUQmTfm?KX8=1 zASv)ZbJJ9w+*_X8T>sq**wWLpSZ-3zCjH-W_tI2*^bRQ2vc4|KH8M(DY%n8QfTQbN zpJZewAJ5LsMa!)>s3d*lG|Vnt`NHY#%Vmr&*Dp;h=qg#b)FHleUxtpNvexzsS3<Vz zSj?BRTs20yp8cI?{4cA_kX++UGp?SS_{Zbgf)mXL3@X;l64EmGVSZoqi?rhIpNjwe z&%LdhIZ-z0vC%pHcIL~i$v5OoB-B)dPi)m(Q;-qext8_#`A-!R6^n)U>$s@1?W;bq z)!^{MaQ8i1&-cx<njjdsQsv!u|3#n9$7WsL_x(5He1rSWQoS$h)ytH%t=9K4cGliI zsa1XX2LHLgd$NnwUU$8JsBt>#O?$&nmFa)u7hI@3`|shFD|`nVY{lc8m!IFF&|M+Y zKl!D})Ih7C%sF@5ge6X!oOAS1&tlrywfyDJd)KCkKd-xd;3Ct9Q`H>b7A+Nj#9Ev6 z(XH(uJ18Ew7#KJhK=CknBclp4Z&K3a8;rWld`U@@Ihf?Yv?h}(m=0vp0@HO&CSZCi zlNVS$6Z2UxeTlgnB)<7S8#gDIk-##C3C!RXs1XD)Cif`L0@IpGlR02fKlzA~6<Cl_ z*#vBkg|aP}U!klArdKMPg6W6K5Os1YE?|DDN)%ZAA(db-EuosL05X*OpWvTc91INW z1Q-~^7!Y7dV=&8PK6Z)8vT8hFh5tV_@AhY6V7SK0z+i+>$FQU^k#}-Fi^=4hsytwu Rbkuf%>6dC5U^+zI0{~|C6Mp~z delta 690 zcmbQ^KgVAvz?+#xgn@yBgCV3bG3xYJlh}zuO7*_MhZO|&rmOvLv}ah7dF#rZHF8@X zANSdMZ~KOgKEjt8eY5`WHMwe0Ci9g+=S}kc$GYDWd^_j;;I_(_irz5M<I#&#iUL`7 z_9AcOthT(lw6gc*g^e3e^mSBbYn>IZIz7K^#i6Y>eSH%(dzrYV{@A>bi+kC1zH;97 zX=Zm8zwS9yT>s?2+;2<IPYyF*m(X4L*fv`JhLGuQ#;(P;tHKj|r~P|o-CU<EGFkr9 z|0glJ@42=q-umfu>TjLC&r8;=)y-iILJpU1TxwLmu9YQQRXIuhv4(^#?`bA0i683< za}V&f&zI%AW>;1B#^K<CYnRvDw|9`8SDl{o``UZ<KOrr0pFVcf*C)&mIlEpeJ1}tm z_f>jvykDJ98RXyE8sMwDy&@o#`L?2fqGsrSaf>p?;tGrPJ?dLt__a>IF;h5qX1~zV z&pO_dI%h4J@ysAt+|%mXW|@H0%`66I)qcLbcPcdg+}~x6lbolNeh|1jeOjD{z?X%p z5|ZxkLGi%Fz`(%(iigP?8C95r8WShqVAN#}ZcLoa!6XN!HJMbILmCq&2Qq1a={hD8 zFuj$@3#^`r`7D^e#M}*1zd4V04ilJ>z{1T5X7CEs2!gfrD9!@Yno5&7U{OE$h>{gp zkWtwLY>tJpElAho3S~Voy;9i}EdNj$qE1f51<X%Xi2|!Xq!J9KB~)|4>d&Z3GX=9u zuH`kEEUU(&5Zss;#r;q4&n*rHhIIlA3}Orju%z)5+vI!}iOG9adBA#g)OLZ*eyNrL IrbE;{01wp~v;Y7A diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java index 5c93c4c021..ba1a0e76da 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java @@ -6,7 +6,7 @@ import at.tuwien.api.error.ApiErrorDto; import at.tuwien.api.user.UserDto; import at.tuwien.exception.*; import at.tuwien.service.AccessService; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -31,13 +31,13 @@ import java.util.UUID; @RequestMapping(path = "/api/database/{databaseId}/access") public class AccessEndpoint extends RestEndpoint { + private final CacheService cacheService; private final AccessService accessService; - private final CredentialService credentialService; @Autowired - public AccessEndpoint(AccessService accessService, CredentialService credentialService) { + public AccessEndpoint(CacheService cacheService, AccessService accessService) { + this.cacheService = cacheService; this.accessService = accessService; - this.credentialService = credentialService; } @PostMapping("/{userId}") @@ -80,8 +80,8 @@ public class AccessEndpoint extends RestEndpoint { throws NotAllowedException, DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseMalformedException, MetadataServiceException { log.debug("endpoint give access to database, databaseId={}, userId={}", databaseId, userId); - final DatabaseDto database = credentialService.getDatabase(databaseId); - final UserDto user = credentialService.getUser(userId); + final DatabaseDto database = cacheService.getDatabase(databaseId); + final UserDto user = cacheService.getUser(userId); if (database.getAccesses().stream().anyMatch(a -> a.getUser().getId().equals(userId))) { log.error("Failed to create access to user with id {}: already has access", userId); throw new NotAllowedException("Failed to create access to user with id " + userId + ": already has access"); @@ -137,8 +137,8 @@ public class AccessEndpoint extends RestEndpoint { DatabaseMalformedException, MetadataServiceException { log.debug("endpoint modify access to database, databaseId={}, userId={}, access.type={}", databaseId, userId, access.getType()); - final DatabaseDto database = credentialService.getDatabase(databaseId); - final UserDto user = credentialService.getUser(userId); + final DatabaseDto database = cacheService.getDatabase(databaseId); + final UserDto user = cacheService.getUser(userId); if (database.getAccesses().stream().noneMatch(a -> a.getHuserid().equals(userId))) { log.error("Failed to update access to user with id {}: no access", userId); throw new NotAllowedException("Failed to update access to user with id " + userId + ": no access"); @@ -192,8 +192,8 @@ public class AccessEndpoint extends RestEndpoint { DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, DatabaseMalformedException, MetadataServiceException { log.debug("endpoint revoke access to database, databaseId={}, userId={}", databaseId, userId); - final DatabaseDto database = credentialService.getDatabase(databaseId); - final UserDto user = credentialService.getUser(userId); + final DatabaseDto database = cacheService.getDatabase(databaseId); + final UserDto user = cacheService.getUser(userId); if (database.getAccesses().stream().noneMatch(a -> a.getUser().getId().equals(userId))) { log.error("Failed to delete access to user with id {}: no access", userId); throw new NotAllowedException("Failed to delete access to user with id " + userId + ": no access"); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java index 0d12384dfa..801c6b638f 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java @@ -10,7 +10,7 @@ import at.tuwien.api.user.internal.UpdateUserPasswordDto; import at.tuwien.exception.*; import at.tuwien.service.AccessService; import at.tuwien.service.ContainerService; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import at.tuwien.service.DatabaseService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -36,18 +36,18 @@ import java.util.UUID; @RequestMapping(path = "/api/database") public class DatabaseEndpoint extends RestEndpoint { + private final CacheService cacheService; private final AccessService accessService; private final DatabaseService databaseService; private final ContainerService containerService; - private final CredentialService credentialService; @Autowired - public DatabaseEndpoint(AccessService accessService, DatabaseService databaseService, - ContainerService containerService, CredentialService credentialService) { + public DatabaseEndpoint(CacheService cacheService, AccessService accessService, DatabaseService databaseService, + ContainerService containerService) { + this.cacheService = cacheService; this.accessService = accessService; this.databaseService = databaseService; this.containerService = containerService; - this.credentialService = credentialService; } @PostMapping @@ -87,7 +87,7 @@ public class DatabaseEndpoint extends RestEndpoint { DatabaseMalformedException, QueryStoreCreateException, MetadataServiceException { log.debug("endpoint create database, data.containerId={}, data.internalName={}, data.username={}", data.getContainerId(), data.getInternalName(), data.getUsername()); - final ContainerDto container = credentialService.getContainer(data.getContainerId()); + final ContainerDto container = cacheService.getContainer(data.getContainerId()); try { final DatabaseDto database = containerService.createDatabase(container, data); containerService.createQueryStore(container, data.getInternalName()); @@ -135,7 +135,7 @@ public class DatabaseEndpoint extends RestEndpoint { DatabaseMalformedException, MetadataServiceException { log.debug("endpoint update user password in database, databaseId={}, data.username={}", databaseId, data.getUsername()); - final DatabaseDto database = credentialService.getDatabase(databaseId); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { databaseService.update(database, data); return ResponseEntity.status(HttpStatus.ACCEPTED) diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java index c63ae3f2a2..e64deaa758 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/SubsetEndpoint.java @@ -49,26 +49,26 @@ import java.util.UUID; @RequestMapping(path = "/api/database/{databaseId}/subset") public class SubsetEndpoint extends RestEndpoint { + private final CacheService cacheService; private final MariaDbMapper mariaDbMapper; private final SubsetService subsetService; private final MetadataMapper metadataMapper; private final MetricsService metricsService; private final StorageService storageService; private final DatabaseService databaseService; - private final CredentialService credentialService; private final EndpointValidator endpointValidator; @Autowired - public SubsetEndpoint(MariaDbMapper mariaDbMapper, SubsetService subsetService, MetadataMapper metadataMapper, - MetricsService metricsService, StorageService storageService, DatabaseService databaseService, - CredentialService credentialService, EndpointValidator endpointValidator) { + public SubsetEndpoint(CacheService cacheService, MariaDbMapper mariaDbMapper, SubsetService subsetService, + MetadataMapper metadataMapper, MetricsService metricsService, StorageService storageService, + DatabaseService databaseService, EndpointValidator endpointValidator) { + this.cacheService = cacheService; this.mariaDbMapper = mariaDbMapper; this.subsetService = subsetService; this.metadataMapper = metadataMapper; this.metricsService = metricsService; this.storageService = storageService; this.databaseService = databaseService; - this.credentialService = credentialService; this.endpointValidator = endpointValidator; } @@ -105,7 +105,7 @@ public class SubsetEndpoint extends RestEndpoint { throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, QueryNotFoundException, NotAllowedException, MetadataServiceException { log.debug("endpoint find subsets in database, databaseId={}, filterPersisted={}", databaseId, filterPersisted); - final DatabaseDto database = credentialService.getDatabase(databaseId); + final DatabaseDto database = cacheService.getDatabase(databaseId); endpointValidator.validateOnlyPrivateSchemaAccess(database, principal); final List<QueryDto> queries; try { @@ -166,7 +166,7 @@ public class SubsetEndpoint extends RestEndpoint { MetadataServiceException, TableNotFoundException, QueryMalformedException, NotAllowedException { log.debug("endpoint find subset in database, databaseId={}, subsetId={}, accept={}, timestamp={}", databaseId, subsetId, accept, timestamp); - final DatabaseDto database = credentialService.getDatabase(databaseId); + final DatabaseDto database = cacheService.getDatabase(databaseId); endpointValidator.validateOnlyPrivateSchemaAccess(database, principal); final QueryDto subset; try { @@ -283,7 +283,7 @@ public class SubsetEndpoint extends RestEndpoint { log.debug("timestamp not set: default to {}", timestamp); } /* create */ - final DatabaseDto database = credentialService.getDatabase(databaseId); + final DatabaseDto database = cacheService.getDatabase(databaseId); endpointValidator.validateOnlyPrivateSchemaAccess(database, principal); try { final UUID subsetId = subsetService.create(database, data, timestamp, userId); @@ -343,13 +343,13 @@ public class SubsetEndpoint extends RestEndpoint { log.debug("endpoint get subset data, databaseId={}, subsetId={}, principal.name={} page={}, size={}", databaseId, subsetId, principal != null ? principal.getName() : null, page, size); endpointValidator.validateDataParams(page, size); - final DatabaseDto database = credentialService.getDatabase(databaseId); + final DatabaseDto database = cacheService.getDatabase(databaseId); if (!database.getIsPublic()) { if (principal == null) { log.error("Failed to re-execute query: no authentication found"); throw new NotAllowedException("Failed to re-execute query: no authentication found"); } - credentialService.getAccess(databaseId, getId(principal)); + cacheService.getAccess(databaseId, getId(principal)); } log.trace("visibility for database: is_public={}, is_schema_public={}", database.getIsPublic(), database.getIsSchemaPublic()); /* parameters */ @@ -440,8 +440,8 @@ public class SubsetEndpoint extends RestEndpoint { DatabaseUnavailableException, QueryNotFoundException, UserNotFoundException, MetadataServiceException { log.debug("endpoint persist query, databaseId={}, queryId={}, data.persist={}, principal.name={}", databaseId, queryId, data.getPersist(), principal.getName()); - final DatabaseDto database = credentialService.getDatabase(databaseId); - credentialService.getAccess(databaseId, getId(principal)); + final DatabaseDto database = cacheService.getDatabase(databaseId); + cacheService.getAccess(databaseId, getId(principal)); try { subsetService.persist(database, queryId, data.getPersist()); final QueryDto dto = subsetService.findById(database, queryId); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index fc7dd5be79..8a16c455d8 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -49,28 +49,28 @@ import java.util.UUID; @RequestMapping(path = "/api/database/{databaseId}/table") public class TableEndpoint extends RestEndpoint { + private final CacheService cacheService; private final TableService tableService; private final MariaDbMapper mariaDbMapper; private final SubsetService subsetService; private final MetricsService metricsService; private final StorageService storageService; private final DatabaseService databaseService; - private final CredentialService credentialService; private final EndpointValidator endpointValidator; private final MetadataServiceGateway metadataServiceGateway; @Autowired - public TableEndpoint(TableService tableService, MariaDbMapper mariaDbMapper, SubsetService subsetService, - MetricsService metricsService, StorageService storageService, DatabaseService databaseService, - CredentialService credentialService, EndpointValidator endpointValidator, + public TableEndpoint(CacheService cacheService, TableService tableService, MariaDbMapper mariaDbMapper, + SubsetService subsetService, MetricsService metricsService, StorageService storageService, + DatabaseService databaseService, EndpointValidator endpointValidator, MetadataServiceGateway metadataServiceGateway) { + this.cacheService = cacheService; this.tableService = tableService; this.mariaDbMapper = mariaDbMapper; this.subsetService = subsetService; this.metricsService = metricsService; this.storageService = storageService; this.databaseService = databaseService; - this.credentialService = credentialService; this.endpointValidator = endpointValidator; this.metadataServiceGateway = metadataServiceGateway; } @@ -118,7 +118,7 @@ public class TableEndpoint extends RestEndpoint { throw new TableMalformedException("Table must have a primary key"); } /* create */ - final DatabaseDto database = credentialService.getDatabase(databaseId); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { final TableDto table = databaseService.createTable(database, data); return ResponseEntity.status(HttpStatus.CREATED) @@ -159,12 +159,14 @@ public class TableEndpoint extends RestEndpoint { public ResponseEntity<TableDto> update(@NotNull @PathVariable("databaseId") UUID databaseId, @NotNull @PathVariable("tableId") UUID tableId, @Valid @RequestBody TableUpdateDto data) throws RemoteUnavailableException, - TableMalformedException, DatabaseUnavailableException, TableNotFoundException, MetadataServiceException { + TableMalformedException, DatabaseUnavailableException, TableNotFoundException, MetadataServiceException, + DatabaseNotFoundException { log.debug("endpoint update table, databaseId={}, data.description={}", databaseId, data.getDescription()); /* create */ - final TableDto table = credentialService.getTable(databaseId, tableId); + final TableDto table = cacheService.getTable(databaseId, tableId); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { - tableService.updateTable(table, data); + tableService.updateTable(database, table, data); return ResponseEntity.status(HttpStatus.ACCEPTED) .build(); } catch (SQLException e) { @@ -203,11 +205,12 @@ public class TableEndpoint extends RestEndpoint { public ResponseEntity<Void> delete(@NotNull @PathVariable("databaseId") UUID databaseId, @NotNull @PathVariable("tableId") UUID tableId) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - QueryMalformedException, MetadataServiceException { + QueryMalformedException, MetadataServiceException, DatabaseNotFoundException { log.debug("endpoint delete table, databaseId={}, tableId={}", databaseId, tableId); - final TableDto table = credentialService.getTable(databaseId, tableId); + final TableDto table = cacheService.getTable(databaseId, tableId); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { - tableService.delete(table); + tableService.delete(database, table); return ResponseEntity.status(HttpStatus.ACCEPTED) .build(); } catch (SQLException e) { @@ -275,29 +278,29 @@ public class TableEndpoint extends RestEndpoint { timestamp = Instant.now(); log.debug("timestamp not set: default to {}", timestamp); } - final TableDto table = credentialService.getTable(databaseId, tableId); + final TableDto table = cacheService.getTable(databaseId, tableId); + final DatabaseDto database = cacheService.getDatabase(databaseId); if (!table.getIsPublic()) { if (principal == null) { log.error("Failed find table data: authentication required"); throw new NotAllowedException("Failed to find table data: authentication required"); } - credentialService.getAccess(databaseId, getId(principal)); + cacheService.getAccess(databaseId, getId(principal)); } try { final HttpHeaders headers = new HttpHeaders(); if (request.getMethod().equals("HEAD")) { headers.set("Access-Control-Expose-Headers", "X-Count"); - headers.set("X-Count", "" + tableService.getCount(table, timestamp)); + headers.set("X-Count", "" + tableService.getCount(database, table, timestamp)); return ResponseEntity.ok() .headers(headers) .build(); } headers.set("Access-Control-Expose-Headers", "X-Headers"); headers.set("X-Headers", String.join(",", table.getColumns().stream().map(ColumnDto::getInternalName).toList())); - final String query = mariaDbMapper.defaultRawSelectQuery(table.getDatabase().getInternalName(), + final String query = mariaDbMapper.defaultRawSelectQuery(database.getInternalName(), table.getInternalName(), timestamp, page, size); - final Dataset<Row> dataset = subsetService.getData(credentialService.getDatabase(table.getTdbid()), - query); + final Dataset<Row> dataset = subsetService.getData(database, query); metricsService.countTableGetData(databaseId, tableId); return ResponseEntity.ok() .headers(headers) @@ -345,13 +348,14 @@ public class TableEndpoint extends RestEndpoint { @RequestHeader("Authorization") String authorization) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, TableMalformedException, QueryMalformedException, NotAllowedException, StorageUnavailableException, - StorageNotFoundException, MetadataServiceException { + StorageNotFoundException, MetadataServiceException, DatabaseNotFoundException { log.debug("endpoint insert raw table data, databaseId={}, tableId={}", databaseId, tableId); - final TableDto table = credentialService.getTable(databaseId, tableId); - final DatabaseAccessDto access = credentialService.getAccess(databaseId, getId(principal)); + final TableDto table = cacheService.getTable(databaseId, tableId); + final DatabaseAccessDto access = cacheService.getAccess(databaseId, getId(principal)); endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), getId(principal)); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { - tableService.createTuple(table, data); + tableService.createTuple(database, table, data); metadataServiceGateway.updateTableStatistics(databaseId, tableId, authorization); return ResponseEntity.status(HttpStatus.CREATED) .build(); @@ -397,14 +401,16 @@ public class TableEndpoint extends RestEndpoint { @NotNull Principal principal, @RequestHeader("Authorization") String authorization) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - TableMalformedException, QueryMalformedException, NotAllowedException, MetadataServiceException { + TableMalformedException, QueryMalformedException, NotAllowedException, MetadataServiceException, + DatabaseNotFoundException { log.debug("endpoint update raw table data, databaseId={}, tableId={}, data.keys={}", databaseId, tableId, data.getKeys()); - final TableDto table = credentialService.getTable(databaseId, tableId); - final DatabaseAccessDto access = credentialService.getAccess(databaseId, getId(principal)); + final TableDto table = cacheService.getTable(databaseId, tableId); + final DatabaseAccessDto access = cacheService.getAccess(databaseId, getId(principal)); endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), getId(principal)); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { - tableService.updateTuple(table, data); + tableService.updateTuple(database, table, data); metadataServiceGateway.updateTableStatistics(databaseId, tableId, authorization); return ResponseEntity.status(HttpStatus.ACCEPTED) .build(); @@ -450,14 +456,16 @@ public class TableEndpoint extends RestEndpoint { @NotNull Principal principal, @RequestHeader("Authorization") String authorization) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - TableMalformedException, QueryMalformedException, NotAllowedException, MetadataServiceException { + TableMalformedException, QueryMalformedException, NotAllowedException, MetadataServiceException, + DatabaseNotFoundException { log.debug("endpoint delete raw table data, databaseId={}, tableId={}, data.keys={}", databaseId, tableId, data.getKeys()); - final TableDto table = credentialService.getTable(databaseId, tableId); - final DatabaseAccessDto access = credentialService.getAccess(databaseId, getId(principal)); + final TableDto table = cacheService.getTable(databaseId, tableId); + final DatabaseAccessDto access = cacheService.getAccess(databaseId, getId(principal)); endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), getId(principal)); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { - tableService.deleteTuple(table, data); + tableService.deleteTuple(database, table, data); metadataServiceGateway.updateTableStatistics(databaseId, tableId, authorization); return ResponseEntity.status(HttpStatus.ACCEPTED) .build(); @@ -504,7 +512,7 @@ public class TableEndpoint extends RestEndpoint { @RequestParam(value = "size", required = false) Long size, Principal principal) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, NotAllowedException, MetadataServiceException, - PaginationException { + PaginationException, DatabaseNotFoundException { log.debug("endpoint find table history, databaseId={}, tableId={}", databaseId, tableId); if (size != null && size <= 0) { log.error("Invalid size: must be > 0"); @@ -513,16 +521,17 @@ public class TableEndpoint extends RestEndpoint { log.debug("size not set: default to 100L"); size = 100L; } - final TableDto table = credentialService.getTable(databaseId, tableId); + final TableDto table = cacheService.getTable(databaseId, tableId); if (!table.getIsPublic()) { if (principal == null) { log.error("Failed to find table history: no authentication found"); throw new NotAllowedException("Failed to find table history: no authentication found"); } - credentialService.getAccess(databaseId, getId(principal)); + cacheService.getAccess(databaseId, getId(principal)); } + final DatabaseDto database = cacheService.getDatabase(databaseId); try { - final List<TableHistoryDto> dto = tableService.history(table, size); + final List<TableHistoryDto> dto = tableService.history(database, table, size); return ResponseEntity.status(HttpStatus.OK) .body(dto); } catch (SQLException e) { @@ -572,7 +581,7 @@ public class TableEndpoint extends RestEndpoint { throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, DatabaseMalformedException, TableNotFoundException, MetadataServiceException { log.debug("endpoint inspect table schemas, databaseId={}", databaseId); - final DatabaseDto database = credentialService.getDatabase(databaseId); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { return ResponseEntity.ok(databaseService.exploreTables(database)); } catch (SQLException e) { @@ -625,17 +634,18 @@ public class TableEndpoint extends RestEndpoint { timestamp = Instant.now(); log.debug("timestamp not set: default to {}", timestamp); } - final TableDto table = credentialService.getTable(databaseId, tableId); + final TableDto table = cacheService.getTable(databaseId, tableId); if (!table.getIsPublic()) { if (principal == null) { log.error("Failed to export private table: principal is null"); throw new NotAllowedException("Failed to export private table: principal is null"); } - credentialService.getAccess(databaseId, getId(principal)); + cacheService.getAccess(databaseId, getId(principal)); } - final String query = mariaDbMapper.defaultRawSelectQuery(table.getDatabase().getInternalName(), + final DatabaseDto database = cacheService.getDatabase(databaseId); + final String query = mariaDbMapper.defaultRawSelectQuery(database.getInternalName(), table.getInternalName(), timestamp, null, null); - final Dataset<Row> dataset = subsetService.getData(credentialService.getDatabase(table.getTdbid()), + final Dataset<Row> dataset = subsetService.getData(cacheService.getDatabase(table.getDatabaseId()), query); metricsService.countTableGetData(databaseId, tableId); final ExportResourceDto resource = storageService.transformDataset(dataset); @@ -684,17 +694,18 @@ public class TableEndpoint extends RestEndpoint { @RequestHeader("Authorization") String authorization) throws RemoteUnavailableException, TableNotFoundException, NotAllowedException, MetadataServiceException, StorageNotFoundException, MalformedException, StorageUnavailableException, QueryMalformedException, - DatabaseUnavailableException { + DatabaseUnavailableException, DatabaseNotFoundException { log.debug("endpoint insert table data, databaseId={}, tableId={}, data.location={}", databaseId, tableId, data.getLocation()); - final TableDto table = credentialService.getTable(databaseId, tableId); - final DatabaseAccessDto access = credentialService.getAccess(databaseId, getId(principal)); + final TableDto table = cacheService.getTable(databaseId, tableId); + final DatabaseAccessDto access = cacheService.getAccess(databaseId, getId(principal)); endpointValidator.validateOnlyWriteOwnOrWriteAllAccess(access.getType(), table.getOwner().getId(), getId(principal)); if (data.getLineTermination() == null) { data.setLineTermination("\\r\\n"); log.debug("line termination not present, default to {}", data.getLineTermination()); } + final DatabaseDto database = cacheService.getDatabase(databaseId); try { - tableService.importDataset(table, data); + tableService.importDataset(database, table, data); } catch (SQLException | TableMalformedException e) { log.error("Failed to establish connection to database: {}", e.getMessage()); throw new DatabaseUnavailableException("Failed to establish connection to database", e); @@ -734,11 +745,11 @@ public class TableEndpoint extends RestEndpoint { public ResponseEntity<TableStatisticDto> statistic(@NotNull @PathVariable("databaseId") UUID databaseId, @NotNull @PathVariable("tableId") UUID tableId) throws DatabaseUnavailableException, RemoteUnavailableException, TableNotFoundException, - MetadataServiceException, TableMalformedException { + MetadataServiceException, TableMalformedException, DatabaseNotFoundException { log.debug("endpoint generate table statistic, databaseId={}, tableId={}", databaseId, tableId); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { - return ResponseEntity.ok(tableService.getStatistics( - credentialService.getTable(databaseId, tableId))); + return ResponseEntity.ok(tableService.getStatistics(database, cacheService.getTable(databaseId, tableId))); } catch (SQLException e) { log.error("Failed to establish connection to database: {}", e.getMessage()); throw new DatabaseUnavailableException("Failed to establish connection to database", e); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index b9c00d9bcc..430ac4edc5 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -46,25 +46,25 @@ import java.util.UUID; public class ViewEndpoint extends RestEndpoint { private final ViewService viewService; + private final CacheService cacheService; private final MariaDbMapper mariaDbMapper; private final SubsetService subsetService; private final MetricsService metricsService; private final StorageService storageService; private final DatabaseService databaseService; - private final CredentialService credentialService; private final EndpointValidator endpointValidator; @Autowired - public ViewEndpoint(ViewService viewService, MariaDbMapper mariaDbMapper, SubsetService subsetService, - MetricsService metricsService, StorageService storageService, DatabaseService databaseService, - CredentialService credentialService, EndpointValidator endpointValidator) { + public ViewEndpoint(ViewService viewService, CacheService cacheService, MariaDbMapper mariaDbMapper, + SubsetService subsetService, MetricsService metricsService, StorageService storageService, + DatabaseService databaseService, EndpointValidator endpointValidator) { this.viewService = viewService; + this.cacheService = cacheService; this.mariaDbMapper = mariaDbMapper; this.subsetService = subsetService; this.metricsService = metricsService; this.storageService = storageService; this.databaseService = databaseService; - this.credentialService = credentialService; this.endpointValidator = endpointValidator; } @@ -109,7 +109,7 @@ public class ViewEndpoint extends RestEndpoint { throws DatabaseUnavailableException, DatabaseNotFoundException, RemoteUnavailableException, DatabaseMalformedException, MetadataServiceException, ViewNotFoundException { log.debug("endpoint inspect view schemas, databaseId={}", databaseId); - final DatabaseDto database = credentialService.getDatabase(databaseId); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { return ResponseEntity.ok(databaseService.exploreViews(database)); } catch (SQLException e) { @@ -158,7 +158,7 @@ public class ViewEndpoint extends RestEndpoint { /* check */ endpointValidator.validateSubsetParams(data.getQuery()); /* create */ - final DatabaseDto database = credentialService.getDatabase(databaseId); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { return ResponseEntity.status(HttpStatus.CREATED) .body(databaseService.createView(database, mariaDbMapper.nameToInternalName(data.getName()), @@ -201,11 +201,12 @@ public class ViewEndpoint extends RestEndpoint { public ResponseEntity<Void> delete(@NotNull @PathVariable("databaseId") UUID databaseId, @NotNull @PathVariable("viewId") UUID viewId) throws DatabaseUnavailableException, RemoteUnavailableException, ViewNotFoundException, - ViewMalformedException, MetadataServiceException { + ViewMalformedException, MetadataServiceException, DatabaseNotFoundException { log.debug("endpoint delete view, databaseId={}, viewId={}", databaseId, viewId); - final ViewDto view = credentialService.getView(databaseId, viewId); + final ViewDto view = cacheService.getView(databaseId, viewId); + final DatabaseDto database = cacheService.getDatabase(databaseId); try { - viewService.delete(view); + viewService.delete(database, view); return ResponseEntity.status(HttpStatus.ACCEPTED) .build(); } catch (SQLException e) { @@ -278,28 +279,29 @@ public class ViewEndpoint extends RestEndpoint { timestamp = Instant.now(); log.debug("timestamp not set: default to {}", timestamp); } - final ViewDto view = credentialService.getView(databaseId, viewId); + final ViewDto view = cacheService.getView(databaseId, viewId); if (!view.getIsPublic()) { if (principal == null) { log.error("Failed to get data from view: unauthorized"); throw new NotAllowedException("Failed to get data from view: unauthorized"); } - credentialService.getAccess(databaseId, getId(principal)); + cacheService.getAccess(databaseId, getId(principal)); } + final DatabaseDto database = cacheService.getDatabase(databaseId); try { final HttpHeaders headers = new HttpHeaders(); if (request.getMethod().equals("HEAD")) { headers.set("Access-Control-Expose-Headers", "X-Count"); - headers.set("X-Count", "" + viewService.count(view, timestamp)); + headers.set("X-Count", "" + viewService.count(database, view, timestamp)); return ResponseEntity.ok() .headers(headers) .build(); } headers.set("Access-Control-Expose-Headers", "X-Headers"); headers.set("X-Headers", String.join(",", view.getColumns().stream().map(ViewColumnDto::getInternalName).toList())); - final String query = mariaDbMapper.defaultRawSelectQuery(view.getDatabase().getInternalName(), + final String query = mariaDbMapper.defaultRawSelectQuery(database.getInternalName(), view.getInternalName(), timestamp, page, size); - final Dataset<Row> dataset = subsetService.getData(credentialService.getDatabase(databaseId), + final Dataset<Row> dataset = subsetService.getData(cacheService.getDatabase(databaseId), query); metricsService.countViewGetData(databaseId, viewId); return ResponseEntity.ok() @@ -356,17 +358,18 @@ public class ViewEndpoint extends RestEndpoint { log.debug("timestamp not set: default to {}", timestamp); } /* parameters */ - final ViewDto view = credentialService.getView(databaseId, viewId); + final ViewDto view = cacheService.getView(databaseId, viewId); if (!view.getIsPublic()) { if (principal == null) { log.error("Failed to export private view: principal is null"); throw new NotAllowedException("Failed to export private view: principal is null"); } - credentialService.getAccess(databaseId, getId(principal)); + cacheService.getAccess(databaseId, getId(principal)); } - final String query = mariaDbMapper.defaultRawSelectQuery(view.getDatabase().getInternalName(), + final DatabaseDto database = cacheService.getDatabase(databaseId); + final String query = mariaDbMapper.defaultRawSelectQuery(database.getInternalName(), view.getInternalName(), timestamp, null, null); - final Dataset<Row> dataset = subsetService.getData(credentialService.getDatabase(databaseId), + final Dataset<Row> dataset = subsetService.getData(cacheService.getDatabase(databaseId), query); metricsService.countViewGetData(databaseId, viewId); final ExportResourceDto resource = storageService.transformDataset(dataset); diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java index 741f82111b..ebb39f7c18 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java @@ -5,12 +5,11 @@ import at.tuwien.api.database.DatabaseAccessDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.query.FilterDto; import at.tuwien.api.database.query.FilterTypeDto; -import at.tuwien.api.database.query.OrderDto; import at.tuwien.api.database.query.SubsetDto; import at.tuwien.config.QueryConfig; import at.tuwien.endpoints.RestEndpoint; import at.tuwien.exception.*; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -28,10 +27,10 @@ import java.util.regex.Pattern; public class EndpointValidator extends RestEndpoint { private final QueryConfig queryConfig; - private final CredentialService credentialService; + private final CacheService credentialService; @Autowired - public EndpointValidator(QueryConfig queryConfig, CredentialService credentialService) { + public EndpointValidator(QueryConfig queryConfig, CacheService credentialService) { this.queryConfig = queryConfig; this.credentialService = credentialService; } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java index 3cbdf09af1..d41e0609ba 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/AccessEndpointUnitTest.java @@ -6,7 +6,7 @@ import at.tuwien.api.user.UserDto; import at.tuwien.endpoints.AccessEndpoint; import at.tuwien.exception.*; import at.tuwien.service.AccessService; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -34,7 +34,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { private AccessEndpoint accessEndpoint; @MockBean - private CredentialService credentialService; + private CacheService credentialService; @MockBean private AccessService accessService; diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java index 43f7b9353e..e2a6c550d0 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java @@ -7,7 +7,7 @@ import at.tuwien.endpoints.DatabaseEndpoint; import at.tuwien.exception.*; import at.tuwien.service.AccessService; import at.tuwien.service.ContainerService; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import at.tuwien.service.DatabaseService; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; @@ -48,7 +48,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { private DatabaseService databaseService; @MockBean - private CredentialService credentialService; + private CacheService credentialService; @BeforeEach public void beforeEach() { diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java index a6a3802866..b72bceafd1 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/SubsetEndpointUnitTest.java @@ -6,7 +6,7 @@ import at.tuwien.api.database.query.QueryPersistDto; import at.tuwien.api.database.query.SubsetDto; import at.tuwien.endpoints.SubsetEndpoint; import at.tuwien.exception.*; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import at.tuwien.service.DatabaseService; import at.tuwien.service.StorageService; import at.tuwien.service.SubsetService; @@ -63,7 +63,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { private DatabaseService databaseService; @MockBean - private CredentialService credentialService; + private CacheService credentialService; @BeforeEach public void beforeEach() { @@ -464,7 +464,7 @@ public class SubsetEndpointUnitTest extends AbstractUnitTest { @Test public void getData_succeeds() throws DatabaseNotFoundException, RemoteUnavailableException, UserNotFoundException, - NotAllowedException, SQLException, QueryNotFoundException, TableMalformedException, QueryMalformedException, + NotAllowedException, SQLException, QueryNotFoundException, QueryMalformedException, DatabaseUnavailableException, PaginationException, MetadataServiceException, TableNotFoundException, ViewNotFoundException, ViewMalformedException { final Dataset<Row> mock = sparkSession.emptyDataFrame(); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java index 619ccf8cf7..765a7f0cd3 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java @@ -7,7 +7,7 @@ import at.tuwien.api.database.table.*; import at.tuwien.endpoints.TableEndpoint; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import at.tuwien.service.DatabaseService; import at.tuwien.service.SubsetService; import at.tuwien.service.TableService; @@ -68,7 +68,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { private DatabaseService databaseService; @MockBean - private CredentialService credentialService; + private CacheService credentialService; @MockBean private MetadataServiceGateway metadataServiceGateway; @@ -103,10 +103,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - when(databaseService.createTable(DATABASE_1_PRIVILEGED_DTO, TABLE_4_CREATE_INTERNAL_DTO)) - .thenReturn(TABLE_4_PRIVILEGED_DTO); - when(databaseService.inspectTable(DATABASE_1_PRIVILEGED_DTO, TABLE_4_INTERNALNAME)) - .thenReturn(TABLE_4_PRIVILEGED_DTO); + when(databaseService.createTable(DATABASE_1_DTO, TABLE_4_CREATE_INTERNAL_DTO)) + .thenReturn(TABLE_4_DTO); + when(databaseService.inspectTable(DATABASE_1_DTO, TABLE_4_INTERNALNAME)) + .thenReturn(TABLE_4_DTO); /* test */ final ResponseEntity<TableDto> response = tableEndpoint.create(DATABASE_1_ID, TABLE_4_CREATE_INTERNAL_DTO); @@ -170,12 +170,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void statistic_succeeds() throws DatabaseUnavailableException, TableNotFoundException, SQLException, - TableMalformedException, RemoteUnavailableException, MetadataServiceException { + TableMalformedException, RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); - when(tableService.getStatistics(any(TableDto.class))) + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); + when(tableService.getStatistics(any(DatabaseDto.class), any(TableDto.class))) .thenReturn(TABLE_8_STATISTIC_DTO); /* test */ @@ -186,14 +188,16 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void statistic_unavailable_fails() throws TableNotFoundException, TableMalformedException, - RemoteUnavailableException, MetadataServiceException, SQLException { + RemoteUnavailableException, MetadataServiceException, SQLException, DatabaseNotFoundException { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); doThrow(SQLException.class) .when(tableService) - .getStatistics(any(TableDto.class)); + .getStatistics(any(DatabaseDto.class), any(TableDto.class)); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -220,14 +224,17 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void delete_succeeds() throws RemoteUnavailableException, DatabaseUnavailableException, - TableNotFoundException, QueryMalformedException, SQLException, MetadataServiceException { + TableNotFoundException, QueryMalformedException, SQLException, MetadataServiceException, + DatabaseNotFoundException { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); doNothing() .when(tableService) - .delete(TABLE_1_PRIVILEGED_DTO); + .delete(DATABASE_1_DTO, TABLE_1_DTO); /* test */ final ResponseEntity<Void> response = tableEndpoint.delete(DATABASE_1_ID, TABLE_1_ID); @@ -263,14 +270,16 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void delete_unavailable_fails() throws RemoteUnavailableException, TableNotFoundException, SQLException, - MetadataServiceException, QueryMalformedException { + MetadataServiceException, QueryMalformedException, DatabaseNotFoundException { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); doThrow(SQLException.class) .when(tableService) - .delete(TABLE_1_PRIVILEGED_DTO); + .delete(DATABASE_1_DTO, TABLE_1_DTO); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -287,7 +296,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); when(credentialService.getDatabase(DATABASE_3_ID)) .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(subsetService.getData(any(DatabaseDto.class), anyString())) @@ -310,10 +319,12 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); - when(tableService.getCount(eq(TABLE_8_PRIVILEGED_DTO), any(Instant.class))) + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); + when(tableService.getCount(any(DatabaseDto.class), any(TableDto.class), any(Instant.class))) .thenReturn(3L); - when(subsetService.getData(eq(DATABASE_3_PRIVILEGED_DTO), anyString())) + when(subsetService.getData(eq(DATABASE_3_DTO), anyString())) .thenReturn(mock); when(httpServletRequest.getMethod()) .thenReturn("HEAD"); @@ -335,7 +346,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); /* test */ assertThrows(NotAllowedException.class, () -> { @@ -350,7 +361,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); doThrow(NotAllowedException.class) .when(credentialService) .getAccess(DATABASE_1_ID, USER_2_ID); @@ -368,9 +379,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_PRIVILEGED_DTO); + .thenReturn(DATABASE_3_DTO); doThrow(QueryMalformedException.class) .when(subsetService) .getData(any(DatabaseDto.class), anyString()); @@ -390,7 +401,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); doThrow(RemoteUnavailableException.class) .when(credentialService) .getAccess(DATABASE_1_ID, USER_2_ID); @@ -411,7 +422,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); when(credentialService.getDatabase(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_2_ID)) @@ -446,7 +457,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void insertRawTuple_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, StorageUnavailableException, StorageNotFoundException, MetadataServiceException { + SQLException, StorageUnavailableException, StorageNotFoundException, MetadataServiceException, DatabaseNotFoundException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -456,12 +467,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_1_ID)) .thenReturn(DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO); doNothing() .when(tableService) - .createTuple(TABLE_8_PRIVILEGED_DTO, request); + .createTuple(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); doNothing() .when(metadataServiceGateway) .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); @@ -473,7 +486,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME) - public void insertRawTuple_noRole_fails() { + public void insertRawTuple_noRole_fails() throws DatabaseNotFoundException, RemoteUnavailableException, + MetadataServiceException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -481,6 +495,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { }}) .build(); + /* mock */ + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); + /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { tableEndpoint.insertRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); @@ -490,7 +508,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void insertRawTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - MetadataServiceException { + MetadataServiceException, DatabaseNotFoundException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -499,6 +517,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .build(); /* mock */ + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); doThrow(TableNotFoundException.class) .when(credentialService) .getTable(DATABASE_3_ID, TABLE_8_ID); @@ -512,7 +532,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void insertRawTuple_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, MetadataServiceException { + NotAllowedException, MetadataServiceException, DatabaseNotFoundException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -522,7 +542,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_READ_ACCESS_DTO); @@ -536,7 +558,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void insertRawTuple_unavailable_fails() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, MetadataServiceException, TableMalformedException, StorageUnavailableException, - SQLException, QueryMalformedException, StorageNotFoundException { + SQLException, QueryMalformedException, StorageNotFoundException, DatabaseNotFoundException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -546,12 +568,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_1_ID)) .thenReturn(DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO); doThrow(SQLException.class) .when(tableService) - .createTuple(TABLE_8_PRIVILEGED_DTO, request); + .createTuple(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -563,7 +587,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void insertRawTuple_writeOwnAccess_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - StorageUnavailableException, StorageNotFoundException, MetadataServiceException { + StorageUnavailableException, StorageNotFoundException, MetadataServiceException, DatabaseNotFoundException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -573,7 +597,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_1_ID)) .thenReturn(DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO); @@ -584,7 +610,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void insertRawTuple_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, MetadataServiceException { + NotAllowedException, MetadataServiceException, DatabaseNotFoundException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -594,7 +620,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_OWN_ACCESS_DTO); @@ -606,9 +634,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) - public void insertRawTuple_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - StorageUnavailableException, StorageNotFoundException, MetadataServiceException { + public void insertRawTuple_writeAllAccessForeign_succeeds() throws TableNotFoundException, + RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, TableMalformedException, + QueryMalformedException, StorageUnavailableException, StorageNotFoundException, MetadataServiceException, + DatabaseNotFoundException { final TupleDto request = TupleDto.builder() .data(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 7L); @@ -618,7 +647,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_ALL_ACCESS_DTO); @@ -630,7 +661,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, MetadataServiceException { + SQLException, MetadataServiceException, DatabaseNotFoundException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -643,12 +674,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_1_ID)) .thenReturn(DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO); doNothing() .when(tableService) - .updateTuple(TABLE_8_PRIVILEGED_DTO, request); + .updateTuple(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); doNothing() .when(metadataServiceGateway) .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); @@ -660,7 +693,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME) - public void updateTuple_noRole_fails() { + public void updateTuple_noRole_fails() throws DatabaseNotFoundException, RemoteUnavailableException, + MetadataServiceException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -671,6 +705,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { }}) .build(); + /* mock */ + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); + /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { tableEndpoint.updateRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); @@ -680,7 +718,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - MetadataServiceException { + MetadataServiceException, DatabaseNotFoundException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -692,6 +730,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .build(); /* mock */ + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); doThrow(TableNotFoundException.class) .when(credentialService) .getTable(DATABASE_3_ID, TABLE_8_ID); @@ -705,7 +745,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, MetadataServiceException { + NotAllowedException, MetadataServiceException, DatabaseNotFoundException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -718,7 +758,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_READ_ACCESS_DTO); @@ -731,7 +773,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_unavailable_fails() throws TableNotFoundException, RemoteUnavailableException, SQLException, - NotAllowedException, MetadataServiceException, TableMalformedException, QueryMalformedException { + NotAllowedException, MetadataServiceException, TableMalformedException, QueryMalformedException, + DatabaseNotFoundException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -744,12 +787,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_ALL_ACCESS_DTO); doThrow(SQLException.class) .when(tableService) - .updateTuple(TABLE_8_PRIVILEGED_DTO, request); + .updateTuple(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -761,7 +806,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_writeOwnAccess_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, MetadataServiceException { + SQLException, MetadataServiceException, DatabaseNotFoundException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -774,12 +819,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_1_ID)) .thenReturn(DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO); doNothing() .when(tableService) - .updateTuple(TABLE_8_PRIVILEGED_DTO, request); + .updateTuple(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); doNothing() .when(metadataServiceGateway) .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); @@ -792,14 +839,17 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"system"}) public void update_succeeds() throws DatabaseUnavailableException, TableNotFoundException, - TableMalformedException, RemoteUnavailableException, SQLException, MetadataServiceException { + TableMalformedException, RemoteUnavailableException, SQLException, MetadataServiceException, + DatabaseNotFoundException { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); doNothing() .when(tableService) - .updateTable(TABLE_8_PRIVILEGED_DTO, TABLE_8_UPDATE_DTO); + .updateTable(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, TABLE_8_UPDATE_DTO); /* test */ final ResponseEntity<TableDto> response = tableEndpoint.update(DATABASE_3_ID, TABLE_8_ID, TABLE_8_UPDATE_DTO); @@ -809,9 +859,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"system"}) public void update_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - MetadataServiceException { + MetadataServiceException, DatabaseNotFoundException { /* mock */ + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); doThrow(TableNotFoundException.class) .when(credentialService) .getTable(DATABASE_3_ID, TABLE_8_ID); @@ -825,9 +877,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"system"}) public void update_unavailable_fails() throws TableNotFoundException, RemoteUnavailableException, - MetadataServiceException { + MetadataServiceException, DatabaseNotFoundException { /* mock */ + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); doThrow(RemoteUnavailableException.class) .when(credentialService) .getTable(DATABASE_3_ID, TABLE_8_ID); @@ -841,9 +895,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"system"}) public void update_exception_fails() throws TableNotFoundException, RemoteUnavailableException, - MetadataServiceException { + MetadataServiceException, DatabaseNotFoundException { /* mock */ + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); doThrow(MetadataServiceException.class) .when(credentialService) .getTable(DATABASE_3_ID, TABLE_8_ID); @@ -857,7 +913,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, MetadataServiceException { + NotAllowedException, MetadataServiceException, DatabaseNotFoundException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -870,7 +926,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_OWN_ACCESS_DTO); @@ -884,7 +942,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void updateTuple_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - SQLException, MetadataServiceException { + SQLException, MetadataServiceException, DatabaseNotFoundException { final TupleUpdateDto request = TupleUpdateDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -897,12 +955,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_ALL_ACCESS_DTO); doNothing() .when(tableService) - .updateTuple(TABLE_8_PRIVILEGED_DTO, request); + .updateTuple(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); doNothing() .when(metadataServiceGateway) .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); @@ -916,7 +976,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_succeeds() throws DatabaseUnavailableException, TableNotFoundException, TableMalformedException, NotAllowedException, QueryMalformedException, RemoteUnavailableException, - SQLException, MetadataServiceException { + SQLException, MetadataServiceException, DatabaseNotFoundException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -925,12 +985,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_1_ID)) .thenReturn(DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO); doNothing() .when(tableService) - .deleteTuple(TABLE_8_PRIVILEGED_DTO, request); + .deleteTuple(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); doNothing() .when(metadataServiceGateway) .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); @@ -942,13 +1004,18 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME) - public void deleteTuple_noRole_fails() { + public void deleteTuple_noRole_fails() throws DatabaseNotFoundException, RemoteUnavailableException, + MetadataServiceException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); }}) .build(); + /* mock */ + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); + /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { tableEndpoint.deleteRawTuple(DATABASE_3_ID, TABLE_8_ID, request, USER_3_PRINCIPAL, TOKEN_ACCESS_TOKEN); @@ -958,7 +1025,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - MetadataServiceException { + MetadataServiceException, DatabaseNotFoundException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -966,6 +1033,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .build(); /* mock */ + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); doThrow(TableNotFoundException.class) .when(credentialService) .getTable(DATABASE_3_ID, TABLE_8_ID); @@ -979,7 +1048,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, MetadataServiceException { + NotAllowedException, MetadataServiceException, DatabaseNotFoundException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -988,7 +1057,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_READ_ACCESS_DTO); @@ -1001,7 +1072,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_unavailable_fails() throws TableNotFoundException, RemoteUnavailableException, SQLException, - NotAllowedException, MetadataServiceException, TableMalformedException, QueryMalformedException { + NotAllowedException, MetadataServiceException, TableMalformedException, QueryMalformedException, DatabaseNotFoundException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -1010,12 +1081,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_1_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_OWN_ACCESS_DTO); doThrow(SQLException.class) .when(tableService) - .deleteTuple(TABLE_8_PRIVILEGED_DTO, request); + .deleteTuple(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -1027,7 +1100,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_writeOwnAccess_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, TableMalformedException, SQLException, QueryMalformedException, - DatabaseUnavailableException, MetadataServiceException { + DatabaseUnavailableException, MetadataServiceException, DatabaseNotFoundException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -1036,12 +1109,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_1_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_OWN_ACCESS_DTO); doNothing() .when(tableService) - .deleteTuple(TABLE_8_PRIVILEGED_DTO, request); + .deleteTuple(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); doNothing() .when(metadataServiceGateway) .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); @@ -1054,7 +1129,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, MetadataServiceException { + NotAllowedException, MetadataServiceException, DatabaseNotFoundException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -1063,7 +1138,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_OWN_ACCESS_DTO); @@ -1077,7 +1154,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"delete-table-data"}) public void deleteTuple_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, DatabaseUnavailableException, TableMalformedException, QueryMalformedException, - SQLException, MetadataServiceException { + SQLException, MetadataServiceException, DatabaseNotFoundException { final TupleDeleteDto request = TupleDeleteDto.builder() .keys(new HashMap<>() {{ put(COLUMN_8_1_INTERNAL_NAME, 6L); @@ -1086,12 +1163,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_ALL_ACCESS_DTO); doNothing() .when(tableService) - .deleteTuple(TABLE_8_PRIVILEGED_DTO, request); + .deleteTuple(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); doNothing() .when(metadataServiceGateway) .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); @@ -1104,12 +1183,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getHistory_succeeds() throws DatabaseUnavailableException, TableNotFoundException, - RemoteUnavailableException, SQLException, NotAllowedException, MetadataServiceException, PaginationException { + RemoteUnavailableException, SQLException, NotAllowedException, MetadataServiceException, PaginationException, DatabaseNotFoundException { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); - when(tableService.history(TABLE_8_PRIVILEGED_DTO, null)) + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); + when(tableService.history(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, null)) .thenReturn(List.of()); /* test */ @@ -1120,11 +1201,13 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getHistory_privateNoRole_fails() throws TableNotFoundException, RemoteUnavailableException, - MetadataServiceException { + MetadataServiceException, DatabaseNotFoundException { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); /* test */ assertThrows(NotAllowedException.class, () -> { @@ -1146,11 +1229,13 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) public void getHistory_privateNoAccess_fails() throws NotAllowedException, RemoteUnavailableException, - TableNotFoundException, MetadataServiceException { + TableNotFoundException, MetadataServiceException, DatabaseNotFoundException { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); doThrow(NotAllowedException.class) .when(credentialService) .getAccess(DATABASE_1_ID, USER_4_ID); @@ -1164,14 +1249,15 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_2_USERNAME) public void getHistory_private_succeeds() throws NotAllowedException, RemoteUnavailableException, SQLException, - TableNotFoundException, MetadataServiceException, DatabaseUnavailableException, PaginationException { + TableNotFoundException, MetadataServiceException, DatabaseUnavailableException, PaginationException, + DatabaseNotFoundException { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_2_ID)) .thenReturn(DATABASE_1_USER_2_READ_ACCESS_DTO); - when(tableService.history(TABLE_1_PRIVILEGED_DTO, 10L)) + when(tableService.history(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, 10L)) .thenReturn(List.of()); /* test */ @@ -1182,14 +1268,16 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getHistory_unavailable_succeeds() throws RemoteUnavailableException, SQLException, - TableNotFoundException, MetadataServiceException { + TableNotFoundException, MetadataServiceException, DatabaseNotFoundException { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); doThrow(SQLException.class) .when(tableService) - .history(TABLE_8_PRIVILEGED_DTO, 100L); + .history(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, 100L); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -1200,9 +1288,11 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void getHistory_tableNotFound_fails() throws TableNotFoundException, RemoteUnavailableException, - MetadataServiceException { + MetadataServiceException, DatabaseNotFoundException { /* mock */ + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); doThrow(TableNotFoundException.class) .when(credentialService) .getTable(DATABASE_3_ID, TABLE_8_ID); @@ -1221,7 +1311,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); when(credentialService.getDatabase(DATABASE_3_ID)) .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(subsetService.getData(any(DatabaseDto.class), anyString())) @@ -1242,11 +1332,13 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_2_ID)) .thenReturn(access); when(credentialService.getDatabase(DATABASE_1_ID)) - .thenReturn(DATABASE_1_PRIVILEGED_DTO); + .thenReturn(DATABASE_1_DTO); when(subsetService.getData(any(DatabaseDto.class), anyString())) .thenReturn(mock); @@ -1258,11 +1350,13 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) public void exportData_privateNoAccess_fails() throws TableNotFoundException, NotAllowedException, - RemoteUnavailableException, MetadataServiceException { + RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); doThrow(NotAllowedException.class) .when(credentialService) .getAccess(DATABASE_1_ID, USER_4_ID); @@ -1281,9 +1375,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_PRIVILEGED_DTO); - when(databaseService.exploreTables(DATABASE_3_PRIVILEGED_DTO)) - .thenReturn(List.of(TABLE_8_PRIVILEGED_DTO)); + .thenReturn(DATABASE_3_DTO); + when(databaseService.exploreTables(DATABASE_3_DTO)) + .thenReturn(List.of(TABLE_8_DTO)); /* test */ final ResponseEntity<List<TableDto>> response = tableEndpoint.getSchema(DATABASE_3_ID); @@ -1317,10 +1411,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_PRIVILEGED_DTO); + .thenReturn(DATABASE_3_DTO); doThrow(SQLException.class) .when(databaseService) - .exploreTables(DATABASE_3_PRIVILEGED_DTO); + .exploreTables(DATABASE_3_DTO); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -1331,7 +1425,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void importDataset_succeeds() throws TableNotFoundException, NotAllowedException, RemoteUnavailableException, - MetadataServiceException, StorageNotFoundException, MalformedException, StorageUnavailableException, DatabaseUnavailableException, QueryMalformedException, SQLException, TableMalformedException { + MetadataServiceException, StorageNotFoundException, MalformedException, StorageUnavailableException, + DatabaseUnavailableException, QueryMalformedException, SQLException, TableMalformedException, + DatabaseNotFoundException { final ImportDto request = ImportDto.builder() .header(true) .lineTermination(null) @@ -1340,12 +1436,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_1_ID)) .thenReturn(DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO); doNothing() .when(tableService) - .importDataset(TABLE_8_PRIVILEGED_DTO, request); + .importDataset(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); doNothing() .when(metadataServiceGateway) .updateTableStatistics(DATABASE_3_ID, TABLE_8_ID, TOKEN_ACCESS_TOKEN); @@ -1395,7 +1493,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importDataset_unavailable_fails() throws RemoteUnavailableException, TableNotFoundException, MetadataServiceException, NotAllowedException, StorageNotFoundException, MalformedException, - StorageUnavailableException, SQLException, QueryMalformedException, TableMalformedException { + StorageUnavailableException, SQLException, QueryMalformedException, TableMalformedException, DatabaseNotFoundException { final ImportDto request = ImportDto.builder() .header(true) .lineTermination("\\n") @@ -1404,12 +1502,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_ALL_ACCESS_DTO); doThrow(SQLException.class) .when(tableService) - .importDataset(any(TableDto.class), eq(request)); + .importDataset(any(DatabaseDto.class), any(TableDto.class), eq(request)); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -1421,7 +1521,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importDataset_writeOwnAccess_fails() throws RemoteUnavailableException, TableNotFoundException, MetadataServiceException, NotAllowedException, StorageNotFoundException, MalformedException, - StorageUnavailableException, SQLException, QueryMalformedException, TableMalformedException { + StorageUnavailableException, SQLException, QueryMalformedException, TableMalformedException, + DatabaseNotFoundException { final ImportDto request = ImportDto.builder() .header(true) .lineTermination("\\n") @@ -1430,12 +1531,14 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_OWN_ACCESS_DTO); doThrow(SQLException.class) .when(tableService) - .importDataset(any(TableDto.class), eq(request)); + .importDataset(any(DatabaseDto.class), any(TableDto.class), eq(request)); /* test */ assertThrows(NotAllowedException.class, () -> { @@ -1446,7 +1549,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importDataset_readAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, MetadataServiceException { + NotAllowedException, MetadataServiceException, DatabaseNotFoundException { final ImportDto request = ImportDto.builder() .header(true) .lineTermination("\\n") @@ -1455,7 +1558,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_READ_ACCESS_DTO); @@ -1469,7 +1574,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"}) public void importDataset_writeOwnAccess_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, MetadataServiceException, StorageNotFoundException, MalformedException, - StorageUnavailableException, DatabaseUnavailableException, QueryMalformedException { + StorageUnavailableException, DatabaseUnavailableException, QueryMalformedException, + DatabaseNotFoundException { final ImportDto request = ImportDto.builder() .header(true) .lineTermination("\\n") @@ -1478,7 +1584,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_1_ID)) .thenReturn(DATABASE_3_USER_1_WRITE_OWN_ACCESS_DTO); @@ -1489,7 +1597,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importDataset_writeOwnAccessForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, MetadataServiceException { + NotAllowedException, MetadataServiceException, DatabaseNotFoundException { final ImportDto request = ImportDto.builder() .header(true) .lineTermination("\\n") @@ -1498,7 +1606,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_3_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_OWN_ACCESS_DTO); @@ -1512,7 +1622,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_3_USERNAME, authorities = {"insert-table-data"}) public void importDataset_writeAllAccessForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, MetadataServiceException, StorageNotFoundException, - MalformedException, StorageUnavailableException, DatabaseUnavailableException, QueryMalformedException { + MalformedException, StorageUnavailableException, DatabaseUnavailableException, QueryMalformedException, + DatabaseNotFoundException { final ImportDto request = ImportDto.builder() .header(true) .lineTermination("\\n") @@ -1521,7 +1632,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_PRIVILEGED_DTO); + .thenReturn(TABLE_8_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_3_ID, USER_1_ID)) .thenReturn(DATABASE_3_USER_3_WRITE_ALL_ACCESS_DTO); @@ -1533,7 +1646,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_2_USERNAME, authorities = {"insert-table-data"}) public void importDataset_privateForeign_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, MetadataServiceException, StorageNotFoundException, MalformedException, - StorageUnavailableException, DatabaseUnavailableException, QueryMalformedException { + StorageUnavailableException, DatabaseUnavailableException, QueryMalformedException, + DatabaseNotFoundException { final ImportDto request = ImportDto.builder() .header(true) .lineTermination("\\n") @@ -1542,7 +1656,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_2_ID)) .thenReturn(DATABASE_1_USER_2_WRITE_ALL_ACCESS_DTO); @@ -1554,7 +1670,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @WithMockUser(username = USER_2_USERNAME, authorities = {"insert-table-data"}) public void importDataset_private_succeeds() throws TableNotFoundException, RemoteUnavailableException, NotAllowedException, MetadataServiceException, StorageNotFoundException, MalformedException, - StorageUnavailableException, DatabaseUnavailableException, QueryMalformedException { + StorageUnavailableException, DatabaseUnavailableException, QueryMalformedException, + DatabaseNotFoundException { final ImportDto request = ImportDto.builder() .header(true) .lineTermination("\\n") @@ -1563,7 +1680,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_2_ID)) - .thenReturn(TABLE_2_PRIVILEGED_DTO); + .thenReturn(TABLE_2_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_2_ID)) .thenReturn(DATABASE_1_USER_2_WRITE_OWN_ACCESS_DTO); @@ -1574,7 +1693,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, authorities = {"insert-table-data"}) public void importDataset_privateForeign_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, MetadataServiceException { + NotAllowedException, MetadataServiceException, DatabaseNotFoundException { final ImportDto request = ImportDto.builder() .header(true) .lineTermination("\\n") @@ -1583,7 +1702,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_2_ID)) .thenReturn(DATABASE_1_USER_2_WRITE_OWN_ACCESS_DTO); @@ -1596,7 +1717,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, authorities = {"insert-table-data"}) public void importDataset_privateReadAccess_fails() throws TableNotFoundException, RemoteUnavailableException, - NotAllowedException, MetadataServiceException { + NotAllowedException, MetadataServiceException, DatabaseNotFoundException { final ImportDto request = ImportDto.builder() .header(true) .lineTermination("\\n") @@ -1605,7 +1726,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_2_ID)) - .thenReturn(TABLE_2_PRIVILEGED_DTO); + .thenReturn(TABLE_2_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_2_ID)) .thenReturn(DATABASE_1_USER_2_READ_ACCESS_DTO); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java index 3c38265a54..0393be3dad 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java @@ -4,7 +4,7 @@ import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.ViewDto; import at.tuwien.endpoints.ViewEndpoint; import at.tuwien.exception.*; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import at.tuwien.service.DatabaseService; import at.tuwien.service.SubsetService; import at.tuwien.service.ViewService; @@ -47,7 +47,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { private DatabaseService databaseService; @MockBean - private CredentialService credentialService; + private CacheService credentialService; @MockBean private HttpServletRequest httpServletRequest; @@ -74,9 +74,9 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) - .thenReturn(DATABASE_1_PRIVILEGED_DTO); + .thenReturn(DATABASE_1_DTO); when(databaseService.createView(any(DatabaseDto.class), anyString(), anyString())) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(VIEW_1_DTO); /* test */ final ResponseEntity<ViewDto> response = viewEndpoint.create(DATABASE_1_ID, VIEW_1_CREATE_DTO); @@ -90,7 +90,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) - .thenReturn(DATABASE_1_PRIVILEGED_DTO); + .thenReturn(DATABASE_1_DTO); doThrow(SQLException.class) .when(databaseService) .createView(any(DatabaseDto.class), anyString(), anyString()); @@ -108,9 +108,9 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) - .thenReturn(DATABASE_1_PRIVILEGED_DTO); - when(databaseService.createView(DATABASE_1_PRIVILEGED_DTO, VIEW_1_NAME, VIEW_1_QUERY)) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(DATABASE_1_DTO); + when(databaseService.createView(DATABASE_1_DTO, VIEW_1_NAME, VIEW_1_QUERY)) + .thenReturn(VIEW_1_DTO); /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { @@ -141,8 +141,8 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) - .thenReturn(DATABASE_1_PRIVILEGED_DTO); - when(databaseService.exploreViews(DATABASE_1_PRIVILEGED_DTO)) + .thenReturn(DATABASE_1_DTO); + when(databaseService.exploreViews(DATABASE_1_DTO)) .thenReturn(List.of(VIEW_1_DTO, VIEW_2_DTO, VIEW_3_DTO)); /* test */ @@ -183,10 +183,10 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) - .thenReturn(DATABASE_1_PRIVILEGED_DTO); + .thenReturn(DATABASE_1_DTO); doThrow(SQLException.class) .when(databaseService) - .exploreViews(DATABASE_1_PRIVILEGED_DTO); + .exploreViews(DATABASE_1_DTO); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -207,14 +207,16 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void delete_succeeds() throws RemoteUnavailableException, ViewMalformedException, ViewNotFoundException, - SQLException, DatabaseUnavailableException, MetadataServiceException { + SQLException, DatabaseUnavailableException, MetadataServiceException, DatabaseNotFoundException { /* mock */ when(credentialService.getView(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(VIEW_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); doNothing() .when(viewService) - .delete(VIEW_1_PRIVILEGED_DTO); + .delete(DATABASE_1_PRIVILEGED_DTO, VIEW_1_DTO); /* test */ final ResponseEntity<Void> response = viewEndpoint.delete(DATABASE_1_ID, VIEW_1_ID); @@ -224,14 +226,16 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) public void delete_unavailable_fails() throws RemoteUnavailableException, ViewMalformedException, SQLException, - MetadataServiceException, ViewNotFoundException { + MetadataServiceException, ViewNotFoundException, DatabaseNotFoundException { /* mock */ when(credentialService.getView(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(VIEW_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); doThrow(SQLException.class) .when(viewService) - .delete(VIEW_1_PRIVILEGED_DTO); + .delete(DATABASE_1_PRIVILEGED_DTO, VIEW_1_DTO); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -249,7 +253,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1_PRIVILEGED_DTO); doNothing() .when(viewService) - .delete(VIEW_1_PRIVILEGED_DTO); + .delete(DATABASE_1_PRIVILEGED_DTO,VIEW_1_DTO); /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { @@ -282,9 +286,9 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getView(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(VIEW_1_DTO); when(credentialService.getDatabase(DATABASE_1_ID)) - .thenReturn(DATABASE_1_PRIVILEGED_DTO); + .thenReturn(DATABASE_1_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_1_ID)) .thenReturn(DATABASE_1_USER_1_READ_ACCESS_DTO); when(subsetService.getData(any(DatabaseDto.class), anyString())) @@ -307,7 +311,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getView(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(VIEW_1_DTO); when(credentialService.getDatabase(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_1_ID)) @@ -331,12 +335,14 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getView(DATABASE_1_ID, VIEW_3_ID)) - .thenReturn(VIEW_3_PRIVILEGED_DTO); + .thenReturn(VIEW_3_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(credentialService.getAccess(DATABASE_1_ID, USER_1_ID)) .thenReturn(DATABASE_1_USER_1_READ_ACCESS_DTO); when(httpServletRequest.getMethod()) .thenReturn("HEAD"); - when(viewService.count(eq(VIEW_3_PRIVILEGED_DTO), any(Instant.class))) + when(viewService.count(any(DatabaseDto.class), eq(VIEW_3_DTO), any(Instant.class))) .thenReturn(VIEW_3_DATA_COUNT); /* test */ @@ -358,7 +364,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getView(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(VIEW_1_DTO); when(httpServletRequest.getMethod()) .thenReturn("GET"); doThrow(NotAllowedException.class) @@ -394,7 +400,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getView(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(VIEW_1_DTO); doThrow(NotAllowedException.class) .when(credentialService) .getAccess(DATABASE_1_ID, USER_4_ID); @@ -412,7 +418,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getView(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(VIEW_1_DTO); doThrow(NotAllowedException.class) .when(credentialService) .getAccess(DATABASE_1_ID, USER_4_ID); @@ -446,7 +452,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getView(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(VIEW_1_DTO); doThrow(NotAllowedException.class) .when(credentialService) .getAccess(DATABASE_1_ID, USER_4_ID); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java index 664e504248..bf58d0fba1 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java @@ -51,24 +51,14 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { @Test public void getTableById_succeeds() throws TableNotFoundException, RemoteUnavailableException, MetadataServiceException { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - headers.set("X-Jdbc-Method", IMAGE_1_JDBC); /* mock */ when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) - .headers(headers) - .body(TABLE_1_PRIVILEGED_DTO)); + .body(TABLE_1_DTO)); /* test */ final TableDto response = metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); - assertEquals(IMAGE_1_JDBC, response.getDatabase().getContainer().getImage().getJdbcMethod()); - assertEquals(CONTAINER_1_HOST, response.getDatabase().getContainer().getHost()); - assertEquals(CONTAINER_1_PORT, response.getDatabase().getContainer().getPort()); - assertEquals(CONTAINER_1_PRIVILEGED_USERNAME, response.getDatabase().getContainer().getUsername()); - assertEquals(CONTAINER_1_PRIVILEGED_PASSWORD, response.getDatabase().getContainer().getPassword()); assertEquals(TABLE_1_INTERNAL_NAME, response.getInternalName()); } @@ -106,7 +96,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.NO_CONTENT) - .body(TABLE_1_PRIVILEGED_DTO)); + .body(TABLE_1_DTO)); /* test */ assertThrows(MetadataServiceException.class, () -> { @@ -127,7 +117,7 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) .thenReturn(ResponseEntity.status(HttpStatus.OK) .headers(headers) - .body(TABLE_1_PRIVILEGED_DTO)); + .body(TABLE_1_DTO)); /* test */ assertThrows(MetadataServiceException.class, () -> { metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); @@ -354,16 +344,11 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { @Test public void getViewById_succeeds() throws RemoteUnavailableException, ViewNotFoundException, MetadataServiceException { - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Username", CONTAINER_1_PRIVILEGED_USERNAME); - headers.set("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD); - headers.set("X-Jdbc-Method", IMAGE_1_JDBC); /* mock */ when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(ViewDto.class))) .thenReturn(ResponseEntity.ok() - .headers(headers) - .body(VIEW_1_PRIVILEGED_DTO)); + .body(VIEW_1_DTO)); /* test */ final ViewDto response = metadataServiceGateway.getViewById(CONTAINER_1_ID, VIEW_1_ID); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java index bca5e11410..2ebb4be18d 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java @@ -2,10 +2,11 @@ package at.tuwien.listener; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; +import at.tuwien.exception.DatabaseNotFoundException; import at.tuwien.exception.MetadataServiceException; import at.tuwien.exception.RemoteUnavailableException; import at.tuwien.exception.TableNotFoundException; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -42,7 +43,7 @@ import static org.mockito.Mockito.when; public class DefaultListenerIntegrationTest extends AbstractUnitTest { @MockBean - private CredentialService credentialService; + private CacheService credentialService; @Autowired private DefaultListener defaultListener; @@ -63,12 +64,14 @@ public class DefaultListenerIntegrationTest extends AbstractUnitTest { @Test public void onMessage_succeeds(CapturedOutput output) throws TableNotFoundException, RemoteUnavailableException, - MetadataServiceException { + MetadataServiceException, DatabaseNotFoundException { final Message request = buildMessage("dbrepo." + DATABASE_1_ID + "." + TABLE_1_ID, "{\"id\":4,\"date\":\"2023-10-03\",\"mintemp\":15.0,\"rainfall\":0.2}", new HashMap<>()); /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); /* test */ defaultListener.onMessage(request); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java index 120f593680..3beec79ab2 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java @@ -2,10 +2,11 @@ package at.tuwien.listener; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; +import at.tuwien.exception.DatabaseNotFoundException; import at.tuwien.exception.MetadataServiceException; import at.tuwien.exception.RemoteUnavailableException; import at.tuwien.exception.TableNotFoundException; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -38,7 +39,7 @@ import static org.mockito.Mockito.when; public class DefaultListenerUnitTest extends AbstractUnitTest { @MockBean - private CredentialService credentialService; + private CacheService credentialService; @Autowired private DefaultListener defaultListener; @@ -53,8 +54,8 @@ public class DefaultListenerUnitTest extends AbstractUnitTest { public void beforeEach() throws SQLException { genesis(); /* metadata database */ - MariaDbConfig.dropAllDatabases(CONTAINER_1_PRIVILEGED_DTO); - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_PRIVILEGED_DTO); + MariaDbConfig.dropAllDatabases(CONTAINER_1_DTO); + MariaDbConfig.createInitDatabase(CONTAINER_1_DTO, DATABASE_1_DTO); } @Test @@ -77,12 +78,14 @@ public class DefaultListenerUnitTest extends AbstractUnitTest { @Test public void onMessage_messageMalformed_fails(CapturedOutput output) throws TableNotFoundException, - RemoteUnavailableException, MetadataServiceException { + RemoteUnavailableException, MetadataServiceException, DatabaseNotFoundException { final Message request = buildMessage(TABLE_1_ROUTING_KEY, "{,}", new HashMap<>()); /* mock */ when(credentialService.getTable(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); /* test */ defaultListener.onMessage(request); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/CredentialServiceUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/CredentialServiceUnitTest.java index a3e7f7ded7..95121ad704 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/CredentialServiceUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/CredentialServiceUnitTest.java @@ -8,7 +8,7 @@ import at.tuwien.api.database.table.TableDto; import at.tuwien.api.user.UserDto; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; -import at.tuwien.service.impl.CredentialServiceImpl; +import at.tuwien.service.impl.CacheServiceImpl; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -30,7 +30,7 @@ import static org.mockito.Mockito.when; public class CredentialServiceUnitTest extends AbstractUnitTest { @Autowired - private CredentialServiceImpl credentialService; + private CacheServiceImpl credentialService; @MockBean private MetadataServiceGateway metadataServiceGateway; @@ -48,7 +48,7 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) - .thenReturn(DATABASE_1_PRIVILEGED_DTO); + .thenReturn(DATABASE_1_DTO); /* test */ final DatabaseDto response = credentialService.getDatabase(DATABASE_1_ID); @@ -62,7 +62,7 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) - .thenReturn(DATABASE_1_PRIVILEGED_DTO) + .thenReturn(DATABASE_1_DTO) .thenThrow(RuntimeException.class) /* should never be thrown */; credentialService.getDatabase(DATABASE_1_ID); @@ -78,8 +78,8 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) - .thenReturn(DATABASE_2_PRIVILEGED_DTO) /* needs to be different id for test case */ - .thenReturn(DATABASE_1_PRIVILEGED_DTO); + .thenReturn(DATABASE_2_DTO) /* needs to be different id for test case */ + .thenReturn(DATABASE_1_DTO); /* pre-condition */ final DatabaseDto tmp = credentialService.getDatabase(DATABASE_1_ID); @@ -98,7 +98,7 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) - .thenReturn(CONTAINER_1_PRIVILEGED_DTO); + .thenReturn(CONTAINER_1_DTO); /* test */ final ContainerDto response = credentialService.getContainer(CONTAINER_1_ID); @@ -128,8 +128,8 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) - .thenReturn(CONTAINER_2_PRIVILEGED_DTO) /* needs to be different id for test case */ - .thenReturn(CONTAINER_1_PRIVILEGED_DTO); + .thenReturn(CONTAINER_2_DTO) /* needs to be different id for test case */ + .thenReturn(CONTAINER_1_DTO); /* pre-condition */ final ContainerDto tmp = credentialService.getContainer(CONTAINER_1_ID); @@ -251,7 +251,7 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); /* test */ final TableDto response = credentialService.getTable(DATABASE_1_ID, TABLE_1_ID); @@ -265,7 +265,7 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO) + .thenReturn(TABLE_1_DTO) .thenThrow(RuntimeException.class) /* should never be thrown */; credentialService.getTable(DATABASE_1_ID, TABLE_1_ID); @@ -281,8 +281,8 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_2_PRIVILEGED_DTO) /* needs to be different id for test case */ - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_2_DTO) /* needs to be different id for test case */ + .thenReturn(TABLE_1_DTO); /* pre-condition */ final TableDto tmp = credentialService.getTable(DATABASE_1_ID, TABLE_1_ID); @@ -301,7 +301,7 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(VIEW_1_DTO); /* test */ final ViewDto response = credentialService.getView(DATABASE_1_ID, VIEW_1_ID); @@ -314,7 +314,7 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_1_PRIVILEGED_DTO) + .thenReturn(VIEW_1_DTO) .thenThrow(RuntimeException.class) /* should never be thrown */; credentialService.getView(DATABASE_1_ID, VIEW_1_ID); @@ -330,8 +330,8 @@ public class CredentialServiceUnitTest extends AbstractUnitTest { /* mock */ when(metadataServiceGateway.getViewById(DATABASE_1_ID, VIEW_1_ID)) - .thenReturn(VIEW_2_PRIVILEGED_DTO) /* needs to be different id for test case */ - .thenReturn(VIEW_1_PRIVILEGED_DTO); + .thenReturn(VIEW_2_DTO) /* needs to be different id for test case */ + .thenReturn(VIEW_1_DTO); /* pre-condition */ final ViewDto tmp = credentialService.getView(DATABASE_1_ID, VIEW_1_ID); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java index c360bc144c..0bd3edc698 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java @@ -84,7 +84,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { final ViewDto view0 = response.get(0); assertEquals("not_in_metadata_db2", view0.getName()); assertEquals("not_in_metadata_db2", view0.getInternalName()); - assertEquals(DATABASE_1_DTO, view0.getDatabase()); + assertEquals(DATABASE_1_ID, view0.getDatabaseId()); assertEquals(USER_1_BRIEF_DTO, view0.getOwner()); assertFalse(view0.getIsInitialView()); assertEquals(DATABASE_1_PUBLIC, view0.getIsPublic()); @@ -149,7 +149,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { final TableDto response = databaseService.inspectTable(DATABASE_1_PRIVILEGED_DTO, "not_in_metadata_db"); assertEquals("not_in_metadata_db", response.getInternalName()); assertEquals("not_in_metadata_db", response.getName()); - assertEquals(DATABASE_1_ID, response.getTdbid()); + assertEquals(DATABASE_1_ID, response.getDatabaseId()); assertTrue(response.getIsVersioned()); assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); final List<ColumnDto> columns = response.getColumns(); @@ -185,7 +185,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { final TableDto response = databaseService.inspectTable(DATABASE_2_PRIVILEGED_DTO, "experiments"); assertEquals("experiments", response.getInternalName()); assertEquals("experiments", response.getName()); - assertEquals(DATABASE_2_ID, response.getTdbid()); + assertEquals(DATABASE_2_ID, response.getDatabaseId()); assertTrue(response.getIsVersioned()); assertEquals(DATABASE_2_PUBLIC, response.getIsPublic()); assertNotNull(response.getOwner()); @@ -218,7 +218,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { final TableDto response = databaseService.inspectTable(DATABASE_1_PRIVILEGED_DTO, "weather_aus"); assertEquals("weather_aus", response.getInternalName()); assertEquals("weather_aus", response.getName()); - assertEquals(DATABASE_1_ID, response.getTdbid()); + assertEquals(DATABASE_1_ID, response.getDatabaseId()); assertTrue(response.getIsVersioned()); assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); assertNotNull(response.getOwner()); @@ -438,7 +438,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { final ViewDto response = databaseService.inspectView(DATABASE_1_PRIVILEGED_DTO, "not_in_metadata_db2"); assertEquals("not_in_metadata_db2", response.getInternalName()); assertEquals("not_in_metadata_db2", response.getName()); - assertEquals(DATABASE_1_DTO, response.getDatabase()); + assertEquals(DATABASE_1_ID, response.getDatabaseId()); assertEquals(USER_1_BRIEF_DTO, response.getOwner()); assertFalse(response.getIsInitialView()); assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); @@ -472,7 +472,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { final TableDto table0 = response.get(0); Assertions.assertEquals("complex_foreign_keys", table0.getInternalName()); Assertions.assertEquals("complex_foreign_keys", table0.getName()); - Assertions.assertEquals(DATABASE_1_ID, table0.getTdbid()); + Assertions.assertEquals(DATABASE_1_ID, table0.getDatabaseId()); assertTrue(table0.getIsVersioned()); Assertions.assertEquals(DATABASE_1_PUBLIC, table0.getIsPublic()); final List<ColumnDto> columns0 = table0.getColumns(); @@ -519,7 +519,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { final TableDto table1 = response.get(1); Assertions.assertEquals("complex_primary_key", table1.getInternalName()); Assertions.assertEquals("complex_primary_key", table1.getName()); - Assertions.assertEquals(DATABASE_1_ID, table1.getTdbid()); + Assertions.assertEquals(DATABASE_1_ID, table1.getDatabaseId()); assertTrue(table1.getIsVersioned()); Assertions.assertEquals(DATABASE_1_PUBLIC, table1.getIsPublic()); final List<ColumnDto> columns1 = table1.getColumns(); @@ -547,7 +547,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { final TableDto table2 = response.get(2); Assertions.assertEquals("exotic_boolean", table2.getInternalName()); Assertions.assertEquals("exotic_boolean", table2.getName()); - Assertions.assertEquals(DATABASE_1_ID, table2.getTdbid()); + Assertions.assertEquals(DATABASE_1_ID, table2.getDatabaseId()); assertTrue(table2.getIsVersioned()); Assertions.assertEquals(DATABASE_1_PUBLIC, table2.getIsPublic()); final List<ColumnDto> columns2 = table2.getColumns(); @@ -568,7 +568,7 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { final TableDto table3 = response.get(3); Assertions.assertEquals("not_in_metadata_db", table3.getInternalName()); Assertions.assertEquals("not_in_metadata_db", table3.getName()); - Assertions.assertEquals(DATABASE_1_ID, table3.getTdbid()); + Assertions.assertEquals(DATABASE_1_ID, table3.getDatabaseId()); assertTrue(table3.getIsVersioned()); Assertions.assertEquals(DATABASE_1_PUBLIC, table3.getIsPublic()); final List<ColumnDto> columns3 = table3.getColumns(); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java index 18b2dd8e01..8ea5e9a973 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java @@ -2,10 +2,7 @@ package at.tuwien.service; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; -import at.tuwien.exception.ContainerNotFoundException; -import at.tuwien.exception.MetadataServiceException; -import at.tuwien.exception.RemoteUnavailableException; -import at.tuwien.exception.TableNotFoundException; +import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.impl.QueueServiceRabbitMqImpl; import at.tuwien.test.AbstractUnitTest; @@ -52,13 +49,13 @@ public class QueueServiceIntegrationTest extends AbstractUnitTest { public void beforeEach() throws SQLException { genesis(); /* metadata database */ - MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_PRIVILEGED_DTO); + MariaDbConfig.dropDatabase(CONTAINER_1_DTO, DATABASE_1_INTERNALNAME); + MariaDbConfig.createInitDatabase(CONTAINER_1_DTO, DATABASE_1_DTO); } @Test - public void insert_succeeds() throws SQLException, RemoteUnavailableException, ContainerNotFoundException, - TableNotFoundException, MetadataServiceException { + public void insert_succeeds() throws SQLException, RemoteUnavailableException, TableNotFoundException, + MetadataServiceException, DatabaseNotFoundException { final Map<String, Object> request = new HashMap<>() {{ put("id", 4L); put("date", "2023-10-03"); @@ -68,29 +65,31 @@ public class QueueServiceIntegrationTest extends AbstractUnitTest { }}; /* mock */ - when(metadataServiceGateway.getContainerById(CONTAINER_1_ID)) - .thenReturn(CONTAINER_1_PRIVILEGED_DTO); + when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); /* test */ - queueService.insert(TABLE_1_PRIVILEGED_DTO, request); + queueService.insert(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); } @Test public void insert_onlyMandatoryFields_succeeds() throws SQLException, RemoteUnavailableException, - TableNotFoundException, MetadataServiceException { + TableNotFoundException, MetadataServiceException, DatabaseNotFoundException { final Map<String, Object> request = new HashMap<>() {{ put("id", 5L); put("date", "2023-10-04"); }}; /* mock */ + when(metadataServiceGateway.getDatabaseById(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID)) - .thenReturn(TABLE_1_PRIVILEGED_DTO); + .thenReturn(TABLE_1_DTO); /* test */ - queueService.insert(TABLE_1_PRIVILEGED_DTO, request); + queueService.insert(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); } } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java index 8ade3cf923..6ec99aaa00 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java @@ -192,7 +192,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { public void reExecuteCount_malformed_fails() { final QueryDto request = QueryDto.builder() .execution(Instant.now()) - .database(DATABASE_1_DTO) + .databaseId(DATABASE_1_ID) .query("SELECT") // <<< .build(); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java index bd4eb4d04b..76c073831a 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java @@ -110,7 +110,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { .build(); /* test */ - tableService.updateTuple(TABLE_1_PRIVILEGED_DTO, request); + tableService.updateTuple(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); final List<Map<String, String>> result = MariaDbConfig.selectQuery(DATABASE_1_PRIVILEGED_DTO, "SELECT id, `date`, location, mintemp, rainfall FROM weather_aus WHERE id = 1", Set.of("id", "date", "location", "mintemp", "rainfall")); assertEquals("1", result.get(0).get("id")); assertEquals("2023-10-03", result.get(0).get("date")); // <<< @@ -137,7 +137,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { .build(); /* test */ - tableService.updateTuple(TABLE_1_PRIVILEGED_DTO, request); + tableService.updateTuple(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); final List<Map<String, String>> result = MariaDbConfig.selectQuery(DATABASE_1_PRIVILEGED_DTO, "SELECT id, `date`, location, mintemp, rainfall FROM weather_aus WHERE id = 4", Set.of("id", "date", "location", "mintemp", "rainfall")); assertEquals("4", result.get(0).get("id")); assertEquals("2023-10-03", result.get(0).get("date")); // <<< @@ -163,7 +163,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { .build(); /* test */ - tableService.updateTuple(TABLE_1_PRIVILEGED_DTO, request); + tableService.updateTuple(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); final List<Map<String, String>> result = MariaDbConfig.selectQuery(DATABASE_1_PRIVILEGED_DTO, "SELECT id, `date`, location, mintemp, rainfall FROM weather_aus WHERE id = 1", Set.of("id", "date", "location", "mintemp", "rainfall")); assertEquals("1", result.get(0).get("id")); assertEquals("2023-10-03", result.get(0).get("date")); // <<< @@ -189,7 +189,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { .build(); /* test */ - tableService.updateTuple(TABLE_1_PRIVILEGED_DTO, request); + tableService.updateTuple(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); final List<Map<String, String>> result = MariaDbConfig.selectQuery(DATABASE_1_PRIVILEGED_DTO, "SELECT id, `date`, location, mintemp, rainfall FROM weather_aus WHERE id = 1", Set.of("id", "date", "location", "mintemp", "rainfall")); assertEquals("1", result.get(0).get("id")); assertEquals("2023-10-03", result.get(0).get("date")); // <<< @@ -213,7 +213,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { .build(); /* test */ - tableService.createTuple(TABLE_1_PRIVILEGED_DTO, request); + tableService.createTuple(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); final List<Map<String, String>> result = MariaDbConfig.selectQuery(DATABASE_1_PRIVILEGED_DTO, "SELECT id, `date`, location, mintemp, rainfall FROM weather_aus WHERE id = 4", Set.of("id", "date", "location", "mintemp", "rainfall")); assertEquals("4", result.get(0).get("id")); assertEquals("2023-10-03", result.get(0).get("date")); @@ -240,7 +240,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { .build(), RequestBody.fromFile(new File("src/test/resources/csv/keyboard.csv"))); /* test */ - tableService.createTuple(TABLE_8_PRIVILEGED_DTO, request); + tableService.createTuple(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, request); final List<Map<String, byte[]>> result = MariaDbConfig.selectQueryByteArr(DATABASE_3_PRIVILEGED_DTO, "SELECT raw FROM mfcc WHERE raw IS NOT NULL", Set.of("raw")); assertNotNull(result.get(0).get("raw")); assertArrayEquals(Files.toByteArray(new File("src/test/resources/csv/keyboard.csv")), result.get(0).get("raw")); @@ -261,7 +261,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { .build(); /* test */ - tableService.createTuple(TABLE_1_PRIVILEGED_DTO, request); + tableService.createTuple(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); final List<Map<String, String>> result = MariaDbConfig.selectQuery(DATABASE_1_PRIVILEGED_DTO, "SELECT id, `date`, location, mintemp, rainfall FROM weather_aus WHERE id = 4", Set.of("id", "date", "location", "mintemp", "rainfall")); assertEquals("4", result.get(0).get("id")); assertEquals("2023-10-03", result.get(0).get("date")); @@ -280,7 +280,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { .build(); /* test */ - tableService.deleteTuple(TABLE_1_PRIVILEGED_DTO, request); + tableService.deleteTuple(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); final List<Map<String, String>> result = MariaDbConfig.selectQuery(DATABASE_1_PRIVILEGED_DTO, "SELECT id FROM weather_aus WHERE id = 1", Set.of("id")); assertEquals(0, result.size()); } @@ -297,7 +297,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { .build(); /* test */ - tableService.deleteTuple(TABLE_1_PRIVILEGED_DTO, request); + tableService.deleteTuple(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); final List<Map<String, String>> result = MariaDbConfig.selectQuery(DATABASE_1_PRIVILEGED_DTO, "SELECT id FROM weather_aus WHERE id = 1", Set.of("id")); assertEquals(0, result.size()); } @@ -307,7 +307,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { public void getStatistics_succeeds() throws TableMalformedException, SQLException, TableNotFoundException { /* test */ - final TableStatisticDto response = tableService.getStatistics(TABLE_2_PRIVILEGED_DTO); + final TableStatisticDto response = tableService.getStatistics(DATABASE_1_PRIVILEGED_DTO, TABLE_2_DTO); assertEquals(TABLE_2_COLUMNS.size(), response.getColumns().size()); log.trace("response rows: {}", response.getRows()); assertEquals(3L, response.getRows()); @@ -336,7 +336,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { public void delete_succeeds() throws SQLException, QueryMalformedException { /* test */ - tableService.delete(TABLE_1_PRIVILEGED_DTO); + tableService.delete(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO); } @Test @@ -347,7 +347,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { /* test */ assertThrows(QueryMalformedException.class, () -> { - tableService.delete(TABLE_5_PRIVILEGED_DTO); + tableService.delete(DATABASE_2_PRIVILEGED_DTO, TABLE_5_DTO); }); } @@ -355,7 +355,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { public void getCount_succeeds() throws SQLException, QueryMalformedException { /* test */ - final Long response = tableService.getCount(TABLE_1_PRIVILEGED_DTO, null); + final Long response = tableService.getCount(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, null); assertEquals(3, response); } @@ -363,7 +363,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { public void getCount_timestamp_succeeds() throws SQLException, QueryMalformedException { /* test */ - final Long response = tableService.getCount(TABLE_1_PRIVILEGED_DTO, Instant.ofEpochSecond(0)); + final Long response = tableService.getCount(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, Instant.ofEpochSecond(0)); assertEquals(0, response); } @@ -375,7 +375,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { /* test */ assertThrows(QueryMalformedException.class, () -> { - tableService.getCount(TABLE_5_PRIVILEGED_DTO, null); + tableService.getCount(DATABASE_2_PRIVILEGED_DTO, TABLE_5_DTO, null); }); } @@ -383,7 +383,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { public void history_succeeds() throws SQLException, TableNotFoundException { /* test */ - final List<TableHistoryDto> response = tableService.history(TABLE_1_PRIVILEGED_DTO, 1000L); + final List<TableHistoryDto> response = tableService.history(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, 1000L); assertEquals(1, response.size()); final TableHistoryDto history0 = response.get(0); assertNotNull(history0.getTimestamp()); @@ -399,7 +399,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - tableService.history(TABLE_5_PRIVILEGED_DTO, null); + tableService.history(DATABASE_2_PRIVILEGED_DTO, TABLE_5_DTO, null); }); } @@ -421,7 +421,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { .build(), RequestBody.fromFile(new File("src/test/resources/csv/weather_aus.csv"))); /* test */ - tableService.importDataset(TABLE_1_PRIVILEGED_DTO, request); + tableService.importDataset(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); } @Test @@ -442,7 +442,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { /* test */ assertThrows(TableMalformedException.class, () -> { - tableService.importDataset(TABLE_1_PRIVILEGED_DTO, request); + tableService.importDataset(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); }); } @@ -464,7 +464,7 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { /* test */ assertThrows(MalformedException.class, () -> { - tableService.importDataset(TABLE_1_PRIVILEGED_DTO, request); + tableService.importDataset(DATABASE_1_PRIVILEGED_DTO, TABLE_1_DTO, request); }); } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java index 2edf7f5f28..9953728632 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java @@ -41,7 +41,7 @@ public class ViewServiceIntegrationTest extends AbstractUnitTest { public void delete_succeeds() throws SQLException, ViewMalformedException { /* test */ - viewService.delete(VIEW_1_PRIVILEGED_DTO); + viewService.delete(DATABASE_1_PRIVILEGED_DTO, VIEW_1_DTO); } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java index d90250f028..cd8cfff2da 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/gateway/impl/MetadataServiceGatewayImpl.java @@ -139,21 +139,11 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { log.error("Failed to find table with id {}: service responded unsuccessful: {}", id, response.getStatusCode()); throw new MetadataServiceException("Failed to find table: service responded unsuccessful: " + response.getStatusCode()); } - final List<String> expectedHeaders = List.of("X-Username", "X-Password", "X-Jdbc-Method"); - if (!response.getHeaders().keySet().containsAll(expectedHeaders)) { - log.error("Failed to find all table headers"); - log.debug("expected headers: {}", expectedHeaders); - log.debug("found headers: {}", response.getHeaders().keySet()); - throw new MetadataServiceException("Failed to find all table headers"); - } if (response.getBody() == null) { log.error("Failed to find table with id {}: body is empty", id); throw new MetadataServiceException("Failed to find table with id " + id + ": body is empty"); } final TableDto table = metadataMapper.tableDtoToTableDto(response.getBody()); - table.getDatabase().getContainer().setUsername(response.getHeaders().get("X-Username").get(0)); - table.getDatabase().getContainer().setPassword(response.getHeaders().get("X-Password").get(0)); - table.getDatabase().getContainer().getImage().setJdbcMethod(response.getHeaders().get("X-Jdbc-Method").get(0)); table.setLastRetrieved(Instant.now()); return table; } @@ -177,21 +167,11 @@ public class MetadataServiceGatewayImpl implements MetadataServiceGateway { log.error("Failed to find view with id {}: service responded unsuccessful: {}", id, response.getStatusCode()); throw new MetadataServiceException("Failed to find view: service responded unsuccessful: " + response.getStatusCode()); } - final List<String> expectedHeaders = List.of("X-Username", "X-Password", "X-Jdbc-Method"); - if (!response.getHeaders().keySet().containsAll(expectedHeaders)) { - log.error("Failed to find all view headers"); - log.debug("expected headers: {}", expectedHeaders); - log.debug("found headers: {}", response.getHeaders().keySet()); - throw new MetadataServiceException("Failed to find all view headers"); - } if (response.getBody() == null) { log.error("Failed to find view with id {}: body is empty", id); throw new MetadataServiceException("Failed to find view with id " + id + ": body is empty"); } final ViewDto view = metadataMapper.viewDtoToViewDto(response.getBody()); - view.getDatabase().getContainer().setUsername(response.getHeaders().get("X-Username").get(0)); - view.getDatabase().getContainer().setPassword(response.getHeaders().get("X-Password").get(0)); - view.getDatabase().getContainer().getImage().setJdbcMethod(response.getHeaders().get("X-Jdbc-Method").get(0)); view.setLastRetrieved(Instant.now()); return view; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java b/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java index 336a483117..929ede0a8f 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/listener/DefaultListener.java @@ -1,10 +1,12 @@ package at.tuwien.listener; +import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.table.TableDto; +import at.tuwien.exception.DatabaseNotFoundException; import at.tuwien.exception.MetadataServiceException; import at.tuwien.exception.RemoteUnavailableException; import at.tuwien.exception.TableNotFoundException; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import at.tuwien.service.QueueService; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; @@ -27,15 +29,15 @@ import java.util.UUID; @Component public class DefaultListener implements MessageListener { + private final CacheService cacheService; private final ObjectMapper objectMapper; private final QueueService queueService; - private final CredentialService credentialService; @Autowired - public DefaultListener(ObjectMapper objectMapper, QueueService queueService, CredentialService credentialService) { + public DefaultListener(CacheService cacheService, ObjectMapper objectMapper, QueueService queueService) { + this.cacheService = cacheService; this.objectMapper = objectMapper; this.queueService = queueService; - this.credentialService = credentialService; } @Override @@ -59,15 +61,18 @@ public class DefaultListener implements MessageListener { log.trace("received message for table with id {} of database id {}: {} bytes", tableId, databaseId, message.getMessageProperties().getContentLength()); final Map<String, Object> body; try { - final TableDto table = credentialService.getTable(databaseId, tableId); + final DatabaseDto database = cacheService.getDatabase(databaseId); + final TableDto table = cacheService.getTable(databaseId, tableId); body = objectMapper.readValue(message.getBody(), typeRef); - queueService.insert(table, body); + queueService.insert(database, table, body); } catch (IOException e) { log.error("Failed to read object: {}", e.getMessage()); } catch (SQLException | RemoteUnavailableException e) { log.error("Failed to insert tuple: {}", e.getMessage()); } catch (TableNotFoundException | MetadataServiceException e) { log.error("Failed to find table: {}", e.getMessage()); + } catch (DatabaseNotFoundException e) { + log.error("Failed to find database: {}", e.getMessage()); } } } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java index 5e0ed68455..9692b48b9e 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/DataMapper.java @@ -48,9 +48,6 @@ public interface DataMapper { ColumnBriefDto columnDtoToColumnBriefDto(ColumnDto data); /* redundant */ - @Mappings({ - @Mapping(target = "databaseId", source = "tdbid") - }) TableBriefDto tableDtoToTableBriefDto(TableDto data); /* redundant */ @@ -58,9 +55,11 @@ public interface DataMapper { ForeignKeyBriefDto foreignKeyDtoToForeignKeyBriefDto(ForeignKeyDto data); - default String rabbitMqTupleToInsertOrUpdateQuery(TableDto table, Map<String, Object> data) { + default String rabbitMqTupleToInsertOrUpdateQuery(String databaseName, TableDto table, Map<String, Object> data) { /* parameterized query for prepared statement */ final StringBuilder statement = new StringBuilder("INSERT INTO `") + .append(databaseName) + .append("`.`") .append(table.getInternalName()) .append("` (") .append(data.keySet() @@ -89,7 +88,7 @@ public interface DataMapper { return ViewDto.builder() .name(resultSet.getString(1)) .internalName(resultSet.getString(1)) - .database(database) + .databaseId(database.getId()) .isInitialView(false) .isPublic(database.getIsPublic()) .isSchemaPublic(database.getIsSchemaPublic()) @@ -129,7 +128,7 @@ public interface DataMapper { .name(resultSet.getString(10)) .internalName(resultSet.getString(10)) .tableId(table.getId()) - .databaseId(table.getTdbid()) + .databaseId(table.getDatabaseId()) .description(resultSet.getString(11)) .build(); final String dataType = resultSet.getString(8); @@ -179,7 +178,7 @@ public interface DataMapper { .d(resultSet.getString(7) != null ? resultSet.getLong(7) : null) .name(resultSet.getString(10)) .internalName(resultSet.getString(10)) - .databaseId(view.getDatabase().getId()) + .databaseId(view.getDatabaseId()) .build(); /* fix boolean and set size for others */ if (resultSet.getString(8).equalsIgnoreCase("tinyint(1)")) { @@ -273,12 +272,12 @@ public interface DataMapper { .column(ColumnBriefDto.builder() .name(columnName) .internalName(columnName) - .databaseId(table.getTdbid()) + .databaseId(table.getDatabaseId()) .build()) .referencedColumn(ColumnBriefDto.builder() .name(referencedColumnName) .internalName(referencedColumnName) - .databaseId(table.getTdbid()) + .databaseId(table.getDatabaseId()) .build()) .build(); if (optional1.isPresent()) { @@ -295,7 +294,7 @@ public interface DataMapper { .referencedTable(TableBriefDto.builder() .name(referencedTable) .internalName(referencedTable) - .databaseId(table.getTdbid()) + .databaseId(table.getDatabaseId()) .build()) .references(new LinkedList<>(List.of(foreignKeyReference))) .onDelete(deleteRule) @@ -325,7 +324,7 @@ public interface DataMapper { .avgRowLength(resultSet.getLong(4)) .dataLength(resultSet.getLong(5)) .maxDataLength(resultSet.getLong(6)) - .tdbid(database.getId()) + .databaseId(database.getId()) .queueName("dbrepo") .routingKey("dbrepo") .description(resultSet.getString(10)) diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java index 7f76b40a8a..7b28a9b2ed 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MariaDbMapper.java @@ -188,10 +188,14 @@ public interface MariaDbMapper { } @Named("dropView") - default String dropViewRawQuery(String viewName) { - final String statement = "DROP VIEW IF EXISTS `" + viewName + "`;"; + default String dropViewRawQuery(String databaseName, String viewName) { + final StringBuilder statement = new StringBuilder("DROP VIEW IF EXISTS `") + .append(databaseName) + .append("`.`") + .append(viewName) + .append("`;"); log.trace("mapped drop view statement: {}", statement); - return statement; + return statement.toString(); } default String databaseViewSelectRawQuery() { @@ -304,16 +308,21 @@ public interface MariaDbMapper { return statement.toString(); } - default String tableNameToUpdateTableRawQuery(String internalName) { + default String tableNameToUpdateTableRawQuery(String databaseName, String internalName) { final StringBuilder stringBuilder = new StringBuilder("ALTER TABLE `") + .append(databaseName) + .append("`.`") .append(internalName) .append("` COMMENT = ?;"); log.trace("mapped update table statement: {}", stringBuilder); return stringBuilder.toString(); } - default String tableCreateDtoToCreateTableRawQuery(at.tuwien.api.database.table.internal.TableCreateDto data) { + default String tableCreateDtoToCreateTableRawQuery(String databaseName, + at.tuwien.api.database.table.internal.TableCreateDto data) { final StringBuilder stringBuilder = new StringBuilder("CREATE TABLE `") + .append(databaseName) + .append("`.`") .append(nameToInternalName(data.getName())) .append("` ("); log.trace("PRIMARY KEY column(s) exist: {}", data.getConstraints().getPrimaryKey()); @@ -484,16 +493,18 @@ public interface MariaDbMapper { } @Named("dropTableQuery") - default String dropTableRawQuery(String tableName) { - return dropTableRawQuery(tableName, true); + default String dropTableRawQuery(String databaseName, String tableName) { + return dropTableRawQuery(databaseName, tableName, true); } - default String dropTableRawQuery(String tableName, Boolean force) { + default String dropTableRawQuery(String databaseName, String tableName, Boolean force) { final StringBuilder statement = new StringBuilder("DROP TABLE "); if (!force) { statement.append("IF EXISTS "); } statement.append("`") + .append(databaseName) + .append("`.`") .append(tableName) .append("`;"); log.trace("mapped drop table query: {}", statement); @@ -522,13 +533,15 @@ public interface MariaDbMapper { return statement.toString(); } - default String tupleToRawDeleteQuery(TableDto table, TupleDeleteDto data) throws TableMalformedException { + default String tupleToRawDeleteQuery(String databaseName, TableDto table, TupleDeleteDto data) throws TableMalformedException { log.trace("table csv to delete query, table.id={}, data.keys={}", table.getId(), data.getKeys()); if (table.getColumns().isEmpty()) { throw new TableMalformedException("Columns are not known"); } /* parameterized query for prepared statement */ final StringBuilder statement = new StringBuilder("DELETE FROM `") + .append(databaseName) + .append("`.`") .append(table.getInternalName()) .append("` WHERE "); final int[] idx = new int[]{0}; @@ -543,14 +556,14 @@ public interface MariaDbMapper { return statement.toString(); } - default String tupleToRawUpdateQuery(TableDto table, TupleUpdateDto data) + default String tupleToRawUpdateQuery(String databaseName, TableDto table, TupleUpdateDto data) throws TableMalformedException { if (table.getColumns().isEmpty()) { throw new TableMalformedException("Columns are not known"); } /* parameterized query for prepared statement */ final StringBuilder statement = new StringBuilder("UPDATE `") - .append(table.getDatabase().getInternalName()) + .append(databaseName) .append("`.`") .append(table.getInternalName()) .append("` SET "); @@ -582,13 +595,13 @@ public interface MariaDbMapper { return statement.toString(); } - default String tupleToRawCreateQuery(TableDto table, TupleDto data) throws TableMalformedException { + default String tupleToRawCreateQuery(String databaseName, TableDto table, TupleDto data) throws TableMalformedException { if (table.getColumns().isEmpty()) { throw new TableMalformedException("Columns are not known"); } /* parameterized query for prepared statement */ final StringBuilder statement = new StringBuilder("INSERT INTO `") - .append(table.getDatabase().getInternalName()) + .append(databaseName) .append("`.`") .append(table.getInternalName()) .append("` ("); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java index 8c9aed92d3..7bdf8fa141 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -7,7 +7,6 @@ import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.ViewColumnDto; import at.tuwien.api.database.ViewDto; import at.tuwien.api.database.query.QueryDto; -import at.tuwien.api.database.query.SubsetDto; import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.columns.ColumnDto; @@ -55,9 +54,6 @@ public interface MetadataMapper { UserBriefDto userDtoToUserBriefDto(UserDto data); - @Mappings({ - @Mapping(target = "databaseId", source = "tdbid") - }) TableBriefDto tableDtoToTableBriefDto(TableDto data); IdentifierBriefDto identifierDtoToIdentifierBriefDto(IdentifierDto data); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/CredentialService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/CacheService.java similarity index 99% rename from dbrepo-data-service/services/src/main/java/at/tuwien/service/CredentialService.java rename to dbrepo-data-service/services/src/main/java/at/tuwien/service/CacheService.java index c52455a29b..c5ffcc1638 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/CredentialService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/CacheService.java @@ -10,7 +10,7 @@ import at.tuwien.exception.*; import java.util.UUID; -public interface CredentialService { +public interface CacheService { /** * Gets credentials for a database with given id either from the cache (if not expired) or retrieves them from the diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/QueueService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/QueueService.java index 6a03f5d767..1e8ba52923 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/QueueService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/QueueService.java @@ -1,5 +1,6 @@ package at.tuwien.service; +import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.table.TableDto; import java.sql.SQLException; @@ -10,9 +11,10 @@ public interface QueueService { /** * Inserts data into the table of a given database. * + * @param database The database. * @param table The table. * @param data The data. * @throws SQLException The connection to the database could not be established. */ - void insert(TableDto table, Map<String, Object> data) throws SQLException; + void insert(DatabaseDto database, TableDto table, Map<String, Object> data) throws SQLException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java index f664a82cf3..bb2b53432c 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/TableService.java @@ -1,5 +1,6 @@ package at.tuwien.service; +import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.query.ImportDto; import at.tuwien.api.database.table.*; import at.tuwien.exception.*; @@ -19,7 +20,7 @@ public interface TableService { * @throws TableMalformedException The table statistic generation was unsuccessful, likely due to a bug in the mapping. * @throws TableNotFoundException The table could not be inspected in the data database. */ - TableStatisticDto getStatistics(TableDto table) throws SQLException, TableMalformedException, + TableStatisticDto getStatistics(DatabaseDto database, TableDto table) throws SQLException, TableMalformedException, TableNotFoundException; /** @@ -31,7 +32,7 @@ public interface TableService { * @throws TableMalformedException The table schema is malformed. * @throws TableNotFoundException The table could not be inspected in the metadata database. */ - void updateTable(TableDto table, TableUpdateDto data) throws SQLException, + void updateTable(DatabaseDto database, TableDto table, TableUpdateDto data) throws SQLException, TableMalformedException, TableNotFoundException; /** @@ -41,7 +42,7 @@ public interface TableService { * @throws SQLException Failed to parse SQL query, contains invalid syntax. * @throws QueryMalformedException The drop table query is malformed. */ - void delete(TableDto table) throws SQLException, QueryMalformedException; + void delete(DatabaseDto database, TableDto table) throws SQLException, QueryMalformedException; /** * Obtains the table history for a given table object. @@ -52,7 +53,7 @@ public interface TableService { * @throws SQLException Failed to parse SQL query, contains invalid syntax. * @throws TableNotFoundException The table could not be found in the data database. */ - List<TableHistoryDto> history(TableDto table, Long size) throws SQLException, TableNotFoundException; + List<TableHistoryDto> history(DatabaseDto database, TableDto table, Long size) throws SQLException, TableNotFoundException; /** * Obtains the table data tuples count at time. @@ -63,7 +64,7 @@ public interface TableService { * @throws SQLException Failed to parse SQL query, contains invalid syntax. * @throws QueryMalformedException The count query is malformed, likely due to a bug in the application. */ - Long getCount(TableDto table, Instant timestamp) throws SQLException, + Long getCount(DatabaseDto database, TableDto table, Instant timestamp) throws SQLException, QueryMalformedException; /** @@ -78,7 +79,7 @@ public interface TableService { * @throws SQLException Failed to parse SQL query, contains invalid syntax. * @throws QueryMalformedException The import query is malformed, likely due to a bug in the application. */ - void importDataset(TableDto table, ImportDto data) throws MalformedException, StorageNotFoundException, + void importDataset(DatabaseDto database, TableDto table, ImportDto data) throws MalformedException, StorageNotFoundException, StorageUnavailableException, SQLException, QueryMalformedException, TableMalformedException; /** @@ -90,7 +91,7 @@ public interface TableService { * @throws TableMalformedException The tuple is malformed and does not fit the table schema. * @throws QueryMalformedException The delete query is malformed, likely due to a bug in the application. */ - void deleteTuple(TableDto table, TupleDeleteDto data) throws SQLException, + void deleteTuple(DatabaseDto database, TableDto table, TupleDeleteDto data) throws SQLException, TableMalformedException, QueryMalformedException; /** @@ -104,7 +105,7 @@ public interface TableService { * @throws StorageUnavailableException Failed to establish a connection with the Storage Service. * @throws StorageNotFoundException The storage service was not able to find the dataset for import. */ - void createTuple(TableDto table, TupleDto data) throws SQLException, + void createTuple(DatabaseDto database, TableDto table, TupleDto data) throws SQLException, QueryMalformedException, TableMalformedException, StorageUnavailableException, StorageNotFoundException; /** @@ -116,6 +117,6 @@ public interface TableService { * @throws QueryMalformedException The update query is malformed, likely due to a bug in the application. * @throws TableMalformedException The tuple is malformed and does not fit the table schema. */ - void updateTuple(TableDto table, TupleUpdateDto data) throws SQLException, + void updateTuple(DatabaseDto database, TableDto table, TupleUpdateDto data) throws SQLException, QueryMalformedException, TableMalformedException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java index 8f721f9974..7f64f72ebe 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/ViewService.java @@ -1,5 +1,6 @@ package at.tuwien.service; +import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.ViewDto; import at.tuwien.exception.QueryMalformedException; import at.tuwien.exception.ViewMalformedException; @@ -12,20 +13,22 @@ public interface ViewService { /** * Deletes a view. * + * @param database The database. * @param view The view. * @throws SQLException The connection to the data database was unsuccessful. * @throws ViewMalformedException The query is malformed and was rejected by the data database. */ - void delete(ViewDto view) throws SQLException, ViewMalformedException; + void delete(DatabaseDto database, ViewDto view) throws SQLException, ViewMalformedException; /** * Counts tuples in a view at system-versioned timestamp. * + * @param database The database. * @param view The view. * @param timestamp The system-versioned timestamp. * @return The number of tuples. * @throws SQLException The connection to the data database was unsuccessful. * @throws QueryMalformedException The query is malformed and was rejected by the data database. */ - Long count(ViewDto view, Instant timestamp) throws SQLException, QueryMalformedException; + Long count(DatabaseDto database, ViewDto view, Instant timestamp) throws SQLException, QueryMalformedException; } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CredentialServiceImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CacheServiceImpl.java similarity index 91% rename from dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CredentialServiceImpl.java rename to dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CacheServiceImpl.java index 79a33866c3..c23f77edd6 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CredentialServiceImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/CacheServiceImpl.java @@ -8,7 +8,7 @@ import at.tuwien.api.database.table.TableDto; import at.tuwien.api.user.UserDto; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; -import at.tuwien.service.CredentialService; +import at.tuwien.service.CacheService; import com.github.benmanes.caffeine.cache.Cache; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; @@ -18,7 +18,7 @@ import java.util.UUID; @Log4j2 @Service -public class CredentialServiceImpl implements CredentialService { +public class CacheServiceImpl implements CacheService { private final MetadataServiceGateway gateway; private final Cache<UUID, UserDto> userCache; @@ -29,10 +29,10 @@ public class CredentialServiceImpl implements CredentialService { private final Cache<UUID, DatabaseAccessDto> accessCache; @Autowired - public CredentialServiceImpl(MetadataServiceGateway gateway, Cache<UUID, UserDto> userCache, - Cache<UUID, ViewDto> viewCache, Cache<UUID, TableDto> tableCache, - Cache<UUID, DatabaseAccessDto> accessCache, Cache<UUID, DatabaseDto> databaseCache, - Cache<UUID, ContainerDto> containerCache) { + public CacheServiceImpl(MetadataServiceGateway gateway, Cache<UUID, UserDto> userCache, + Cache<UUID, ViewDto> viewCache, Cache<UUID, TableDto> tableCache, + Cache<UUID, DatabaseAccessDto> accessCache, Cache<UUID, DatabaseDto> databaseCache, + Cache<UUID, ContainerDto> containerCache) { this.gateway = gateway; this.userCache = userCache; this.viewCache = viewCache; diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DataConnector.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DataConnector.java index 37a345426a..6e6e316b5a 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DataConnector.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DataConnector.java @@ -2,8 +2,6 @@ package at.tuwien.service.impl; import at.tuwien.api.container.ContainerDto; import at.tuwien.api.database.DatabaseDto; -import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableDto; import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Service; @@ -25,14 +23,6 @@ public abstract class DataConnector { return dataSource; } - public ComboPooledDataSource getDataSource(ViewDto view) { - return getDataSource(view.getDatabase().getContainer(), view.getDatabase().getInternalName()); - } - - public ComboPooledDataSource getDataSource(TableDto table) { - return getDataSource(table.getDatabase().getContainer(), table.getDatabase().getInternalName()); - } - public ComboPooledDataSource getDataSource(ContainerDto container) { return getDataSource(container, null); } @@ -48,10 +38,6 @@ public abstract class DataConnector { return sb.toString(); } - public String getSparkUrl(TableDto table) { - return getSparkUrl(table.getDatabase().getContainer(), table.getDatabase().getInternalName()); - } - public String getSparkUrl(DatabaseDto databaseDto) { return getSparkUrl(databaseDto.getContainer(), databaseDto.getInternalName()); } diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java index fc990b0e8e..846fa86a4c 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceMariaDbImpl.java @@ -58,7 +58,7 @@ public class DatabaseServiceMariaDbImpl extends DataConnector implements Databas throw new ViewNotFoundException("Failed to find view in the information schema"); } final ViewDto view = dataMapper.schemaResultSetToView(database, resultSet1); - view.setDatabase(database); + view.setDatabaseId(database.getId()); view.setOwner(database.getOwner()); /* obtain view columns */ start = System.currentTimeMillis(); @@ -96,7 +96,8 @@ public class DatabaseServiceMariaDbImpl extends DataConnector implements Databas try { /* create table if not exists */ final long start = System.currentTimeMillis(); - connection.prepareStatement(mariaDbMapper.tableCreateDtoToCreateTableRawQuery(data)) + connection.prepareStatement(mariaDbMapper.tableCreateDtoToCreateTableRawQuery(database.getInternalName(), + data)) .execute(); log.trace("executed statement in {} ms", System.currentTimeMillis() - start); connection.commit(); @@ -111,7 +112,7 @@ public class DatabaseServiceMariaDbImpl extends DataConnector implements Databas } finally { dataSource.close(); } - log.info("Created table with name {}", tableName); + log.info("Created table with name {}.{}", database.getInternalName(), tableName); return inspectTable(database, tableName); } @@ -131,7 +132,7 @@ public class DatabaseServiceMariaDbImpl extends DataConnector implements Databas .owner(database.getOwner()) .identifiers(new LinkedList<>()) .isInitialView(false) - .database(database) + .databaseId(database.getId()) .columns(new LinkedList<>()) .build(); try { @@ -291,7 +292,7 @@ public class DatabaseServiceMariaDbImpl extends DataConnector implements Databas }); } } - table.setTdbid(database.getId()); + table.setDatabaseId(database.getId()); table.setOwner(database.getOwner()); final TableDto tmpTable = table; tmpTable.getColumns() diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/QueueServiceRabbitMqImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/QueueServiceRabbitMqImpl.java index 4db29335fb..07b889d536 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/QueueServiceRabbitMqImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/QueueServiceRabbitMqImpl.java @@ -1,5 +1,6 @@ package at.tuwien.service.impl; +import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.mapper.DataMapper; @@ -30,13 +31,14 @@ public class QueueServiceRabbitMqImpl extends DataConnector implements QueueServ } @Override - public void insert(TableDto table, Map<String, Object> data) throws SQLException { - final ComboPooledDataSource dataSource = getDataSource(table); + public void insert(DatabaseDto database, TableDto table, Map<String, Object> data) throws SQLException { + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); try { final int[] idx = new int[]{1}; final PreparedStatement preparedStatement = connection.prepareStatement( - dataMapper.rabbitMqTupleToInsertOrUpdateQuery(metadataMapper.tableDtoToTableDto(table), data)); + dataMapper.rabbitMqTupleToInsertOrUpdateQuery(database.getInternalName(), + metadataMapper.tableDtoToTableDto(table), data)); for (Map.Entry<String, Object> entry : data.entrySet()) { final Optional<ColumnDto> optional = table.getColumns().stream().filter(c -> c.getInternalName().equals(entry.getKey())).findFirst(); if (optional.isEmpty()) { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java index 4d3e6df663..869f12bde2 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/SubsetServiceMariaDbImpl.java @@ -147,7 +147,7 @@ public class SubsetServiceMariaDbImpl extends DataConnector implements SubsetSer final QueryDto query = dataMapper.resultSetToQueryDto(resultSet); query.setIdentifiers(metadataServiceGateway.getIdentifiers(database.getId(), queryId)); query.setOwner(database.getOwner()); - query.setDatabase(database); + query.setDatabaseId(database.getId()); return query; } catch (SQLException e) { log.error("Failed to find query with id {}: {}", queryId, e.getMessage()); diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java index 466f7539fd..a646de02b3 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/TableServiceMariaDbImpl.java @@ -1,5 +1,6 @@ package at.tuwien.service.impl; +import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.query.ImportDto; import at.tuwien.api.database.table.*; import at.tuwien.api.database.table.columns.ColumnDto; @@ -50,9 +51,9 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi } @Override - public TableStatisticDto getStatistics(TableDto table) throws SQLException, TableMalformedException, + public TableStatisticDto getStatistics(DatabaseDto database, TableDto table) throws SQLException, TableMalformedException, TableNotFoundException { - final ComboPooledDataSource dataSource = getDataSource(table); + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); final TableStatisticDto statistic; try { @@ -60,14 +61,14 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi final long start = System.currentTimeMillis(); final String query = mariaDbMapper.tableColumnStatisticsSelectRawQuery(table.getColumns(), table.getInternalName()); if (query == null) { - log.debug("table {}.{} does not have columns that can be analysed for statistical properties (i.e. no numeric columns)", table.getDatabase().getInternalName(), table.getInternalName()); + log.debug("table {}.{} does not have columns that can be analysed for statistical properties", database.getInternalName(), table.getInternalName()); statistic = null; } else { final ResultSet resultSet = connection.prepareStatement(query) .executeQuery(); log.trace("executed statement in {} ms", System.currentTimeMillis() - start); statistic = dataMapper.resultSetToTableStatistic(resultSet); - final TableDto tmpTable = databaseService.inspectTable(table.getDatabase(), table.getInternalName()); + final TableDto tmpTable = databaseService.inspectTable(database, table.getInternalName()); statistic.setAvgRowLength(tmpTable.getAvgRowLength()); statistic.setDataLength(tmpTable.getDataLength()); statistic.setMaxDataLength(tmpTable.getMaxDataLength()); @@ -91,14 +92,15 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi } @Override - public void updateTable(TableDto table, TableUpdateDto data) throws SQLException, + public void updateTable(DatabaseDto database, TableDto table, TableUpdateDto data) throws SQLException, TableMalformedException { - final ComboPooledDataSource dataSource = getDataSource(table.getDatabase()); + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); try { /* create table if not exists */ final long start = System.currentTimeMillis(); - final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.tableNameToUpdateTableRawQuery(table.getInternalName())); + final PreparedStatement statement = connection.prepareStatement( + mariaDbMapper.tableNameToUpdateTableRawQuery(database.getInternalName(), table.getInternalName())); log.trace("prepare with arg 1={}", data.getDescription()); if (data.getDescription() == null) { statement.setString(1, ""); @@ -115,17 +117,18 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi } finally { dataSource.close(); } - log.info("Updated table with name {}", table.getInternalName()); + log.info("Updated table with name {}.{}", database.getInternalName(), table.getInternalName()); } @Override - public void delete(TableDto table) throws SQLException, QueryMalformedException { - final ComboPooledDataSource dataSource = getDataSource(table.getDatabase()); + public void delete(DatabaseDto database, TableDto table) throws SQLException, QueryMalformedException { + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); try { /* create table if not exists */ final long start = System.currentTimeMillis(); - connection.prepareStatement(mariaDbMapper.dropTableRawQuery(table.getInternalName())) + connection.prepareStatement(mariaDbMapper.dropTableRawQuery(database.getInternalName(), + table.getInternalName())) .execute(); log.trace("executed statement in {} ms", System.currentTimeMillis() - start); connection.commit(); @@ -136,63 +139,63 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi } finally { dataSource.close(); } - log.info("Deleted table with name {}", table.getInternalName()); + log.info("Deleted table with name {}.{}", database.getInternalName(), table.getInternalName()); } @Override - public List<TableHistoryDto> history(TableDto table, Long size) throws SQLException, + public List<TableHistoryDto> history(DatabaseDto database, TableDto table, Long size) throws SQLException, TableNotFoundException { - final ComboPooledDataSource dataSource = getDataSource(table.getDatabase()); + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); final List<TableHistoryDto> history; try { /* find table data */ final long start = System.currentTimeMillis(); final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.selectHistoryRawQuery( - table.getDatabase().getInternalName(), table.getInternalName(), size)) + database.getInternalName(), table.getInternalName(), size)) .executeQuery(); log.trace("executed statement in {} ms", System.currentTimeMillis() - start); history = dataMapper.resultSetToTableHistory(resultSet); connection.commit(); } catch (SQLException e) { connection.rollback(); - log.error("Failed to find history for table {}.{}: {}", table.getDatabase(), table.getInternalName(), e.getMessage()); - throw new TableNotFoundException("Failed to find history for table " + table.getDatabase() + "." + table.getInternalName() + ": " + e.getMessage(), e); + log.error("Failed to find history for table {}.{}: {}", database, table.getInternalName(), e.getMessage()); + throw new TableNotFoundException("Failed to find history for table " + database + "." + table.getInternalName() + ": " + e.getMessage(), e); } finally { dataSource.close(); } - log.info("Find history for table {}.{}", table.getDatabase(), table.getInternalName()); + log.info("Find history for table {}.{}", database.getInternalName(), table.getInternalName()); return history; } @Override - public Long getCount(TableDto table, Instant timestamp) throws SQLException, + public Long getCount(DatabaseDto database, TableDto table, Instant timestamp) throws SQLException, QueryMalformedException { - final ComboPooledDataSource dataSource = getDataSource(table.getDatabase()); + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); final Long queryResult; try { /* find table data */ final long start = System.currentTimeMillis(); final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.selectCountRawQuery( - table.getDatabase().getInternalName(), table.getInternalName(), timestamp)) + database.getInternalName(), table.getInternalName(), timestamp)) .executeQuery(); log.trace("executed statement in {} ms", System.currentTimeMillis() - start); queryResult = mariaDbMapper.resultSetToNumber(resultSet); connection.commit(); } catch (SQLException e) { connection.rollback(); - log.error("Failed to find row count from table {}.{}: {}", table.getDatabase(), table.getInternalName(), e.getMessage()); - throw new QueryMalformedException("Failed to find row count from table " + table.getDatabase() + "." + table.getInternalName() + ": " + e.getMessage(), e); + log.error("Failed to find row count from table {}.{}: {}", database, table.getInternalName(), e.getMessage()); + throw new QueryMalformedException("Failed to find row count from table " + database + "." + table.getInternalName() + ": " + e.getMessage(), e); } finally { dataSource.close(); } - log.info("Find row count from table {}.{}", table.getDatabase(), table.getInternalName()); + log.info("Find row count from table {}.{}", database.getInternalName(), table.getInternalName()); return queryResult; } @Override - public void importDataset(TableDto table, ImportDto data) throws MalformedException, + public void importDataset(DatabaseDto database, TableDto table, ImportDto data) throws MalformedException, StorageNotFoundException, StorageUnavailableException, SQLException, QueryMalformedException, TableMalformedException { final List<String> columns = table.getColumns() @@ -202,8 +205,8 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi final Dataset<Row> dataset = storageService.loadDataset(columns, data.getLocation(), String.valueOf(data.getSeparator()), data.getHeader()); final Properties properties = new Properties(); - properties.setProperty("user", table.getDatabase().getContainer().getUsername()); - properties.setProperty("password", table.getDatabase().getContainer().getPassword()); + properties.setProperty("user", database.getContainer().getUsername()); + properties.setProperty("password", database.getContainer().getPassword()); final String temporaryTable = table.getInternalName() + "_tmp"; try { log.trace("import dataset to temporary table: {}", temporaryTable); @@ -211,7 +214,7 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi .mode(SaveMode.Overwrite) .option("header", data.getHeader()) .option("inferSchema", "true") - .jdbc(getSparkUrl(table), temporaryTable, properties); + .jdbc(getSparkUrl(database), temporaryTable, properties); } catch (Exception e) { if (e instanceof AnalysisException exception) { final String message = exception.getSimpleMessage() @@ -222,8 +225,8 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi log.error("Failed to write dataset: {}", e.getMessage()); throw new MalformedException("Failed to write dataset: " + e.getMessage()) /* remove throwable on purpose, clutters the output */; } - /* import .csv from sidecar to database */ - final ComboPooledDataSource dataSource = getDataSource(table); + /* import .csv to database */ + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); try { /* import tuple */ @@ -237,25 +240,27 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi throw new QueryMalformedException("Failed to import tuple: " + e.getMessage(), e); } finally { /* delete temporary table */ - connection.prepareStatement(mariaDbMapper.dropTableRawQuery(temporaryTable, false)) + connection.prepareStatement(mariaDbMapper.dropTableRawQuery(database.getInternalName(), temporaryTable, + false)) .execute(); connection.commit(); dataSource.close(); } - log.info("Imported dataset into table: {}.{}", table.getDatabase(), table.getInternalName()); + log.info("Imported dataset into table: {}.{}", database, table.getInternalName()); } @Override - public void deleteTuple(TableDto table, TupleDeleteDto data) throws SQLException, + public void deleteTuple(DatabaseDto database, TableDto table, TupleDeleteDto data) throws SQLException, TableMalformedException, QueryMalformedException { log.trace("delete tuple: {}", data); /* prepare the statement */ - final ComboPooledDataSource dataSource = getDataSource(table); + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); try { /* import tuple */ final int[] idx = new int[]{1}; - final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.tupleToRawDeleteQuery(table, data)); + final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.tupleToRawDeleteQuery( + database.getInternalName(), table, data)); for (String column : data.getKeys().keySet()) { mariaDbMapper.prepareStatementWithColumnTypeObject(statement, getColumnType(table.getColumns(), column), idx[0], column, data.getKeys().get(column)); @@ -272,12 +277,12 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi } finally { dataSource.close(); } - log.info("Deleted tuple(s) from table: {}.{}", table.getDatabase(), table.getInternalName()); + log.info("Deleted tuple(s) from table: {}.{}", database.getInternalName(), table.getInternalName()); } @Override - public void createTuple(TableDto table, TupleDto data) throws SQLException, QueryMalformedException, - TableMalformedException, StorageUnavailableException, StorageNotFoundException { + public void createTuple(DatabaseDto database, TableDto table, TupleDto data) throws SQLException, + QueryMalformedException, TableMalformedException, StorageUnavailableException, StorageNotFoundException { log.trace("create tuple: {}", data); /* for each LOB-like data-column, retrieve the bytes and replace the value */ for (String key : data.getData().keySet()) { @@ -294,12 +299,13 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi .replace(key, blob); } /* prepare the statement */ - final ComboPooledDataSource dataSource = getDataSource(table); + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); try { /* create tuple */ final int[] idx = new int[]{1}; - final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.tupleToRawCreateQuery(table, data)); + final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.tupleToRawCreateQuery( + database.getInternalName(), table, data)); for (Map.Entry<String, Object> entry : data.getData().entrySet()) { mariaDbMapper.prepareStatementWithColumnTypeObject(statement, getColumnType(table.getColumns(), entry.getKey()), idx[0], entry.getKey(), entry.getValue()); @@ -316,19 +322,20 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi } finally { dataSource.close(); } - log.info("Created tuple(s) in table: {}.{}", table.getDatabase(), table.getInternalName()); + log.info("Created tuple(s) in table: {}.{}", database.getInternalName(), table.getInternalName()); } @Override - public void updateTuple(TableDto table, TupleUpdateDto data) throws SQLException, + public void updateTuple(DatabaseDto database, TableDto table, TupleUpdateDto data) throws SQLException, QueryMalformedException, TableMalformedException { log.trace("update tuple: {}", data); /* prepare the statement */ - final ComboPooledDataSource dataSource = getDataSource(table); + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); try { final int[] idx = new int[]{1}; - final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.tupleToRawUpdateQuery(table, data)); + final PreparedStatement statement = connection.prepareStatement(mariaDbMapper.tupleToRawUpdateQuery( + database.getInternalName(), table, data)); /* set data */ for (Map.Entry<String, Object> entry : data.getData().entrySet()) { mariaDbMapper.prepareStatementWithColumnTypeObject(statement, @@ -352,7 +359,7 @@ public class TableServiceMariaDbImpl extends DataConnector implements TableServi } finally { dataSource.close(); } - log.info("Updated tuple(s) from table: {}.{}", table.getDatabase(), table.getInternalName()); + log.info("Updated tuple(s) from table: {}.{}", database.getInternalName(), table.getInternalName()); } public ColumnTypeDto getColumnType(List<ColumnDto> columns, String name) throws QueryMalformedException { diff --git a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java index fff524047e..c1ba33ae4a 100644 --- a/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java +++ b/dbrepo-data-service/services/src/main/java/at/tuwien/service/impl/ViewServiceMariaDbImpl.java @@ -1,5 +1,6 @@ package at.tuwien.service.impl; +import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.ViewDto; import at.tuwien.exception.QueryMalformedException; import at.tuwien.exception.ViewMalformedException; @@ -27,13 +28,14 @@ public class ViewServiceMariaDbImpl extends DataConnector implements ViewService } @Override - public void delete(ViewDto view) throws SQLException, ViewMalformedException { - final ComboPooledDataSource dataSource = getDataSource(view); + public void delete(DatabaseDto database, ViewDto view) throws SQLException, ViewMalformedException { + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); try { /* drop view if exists */ final long start = System.currentTimeMillis(); - connection.prepareStatement(mariaDbMapper.dropViewRawQuery(view.getInternalName())) + connection.prepareStatement(mariaDbMapper.dropViewRawQuery(database.getInternalName(), + view.getInternalName())) .execute(); log.trace("executed statement in {} ms", System.currentTimeMillis() - start); connection.commit(); @@ -44,32 +46,32 @@ public class ViewServiceMariaDbImpl extends DataConnector implements ViewService } finally { dataSource.close(); } - log.info("Deleted view {}.{}", view.getDatabase(), view.getInternalName()); + log.info("Deleted view {}.{}", database.getInternalName(), view.getInternalName()); } @Override - public Long count(ViewDto view, Instant timestamp) throws SQLException, + public Long count(DatabaseDto database, ViewDto view, Instant timestamp) throws SQLException, QueryMalformedException { - final ComboPooledDataSource dataSource = getDataSource(view); + final ComboPooledDataSource dataSource = getDataSource(database); final Connection connection = dataSource.getConnection(); final Long queryResult; try { /* find view data */ final long start = System.currentTimeMillis(); final ResultSet resultSet = connection.prepareStatement(mariaDbMapper.selectCountRawQuery( - view.getDatabase().getInternalName(), view.getInternalName(), timestamp)) + database.getInternalName(), view.getInternalName(), timestamp)) .executeQuery(); log.trace("executed statement in {} ms", System.currentTimeMillis() - start); queryResult = mariaDbMapper.resultSetToNumber(resultSet); connection.commit(); } catch (SQLException e) { connection.rollback(); - log.error("Failed to find row count from view {}.{}: {}", view.getDatabase(), view.getInternalName(), e.getMessage()); - throw new QueryMalformedException("Failed to find row count from view " + view.getDatabase() + "." + view.getInternalName() + ": " + e.getMessage(), e); + log.error("Failed to find row count from view {}.{}: {}", database.getInternalName(), view.getInternalName(), e.getMessage()); + throw new QueryMalformedException("Failed to find row count from view " + database.getInternalName() + "." + view.getInternalName() + ": " + e.getMessage(), e); } finally { dataSource.close(); } - log.info("Find row count from view {}.{}", view.getDatabase(), view.getInternalName()); + log.info("Find row count from view {}.{}", database.getInternalName(), view.getInternalName()); return queryResult; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerDto.java index 35bfafdf46..39eb011652 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerDto.java @@ -2,6 +2,7 @@ package at.tuwien.api.container; import at.tuwien.api.CacheableDto; import at.tuwien.api.container.image.ImageDto; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -35,20 +36,14 @@ public class ContainerDto extends CacheableDto { @Schema(example = "air_quality") private String internalName; + @JsonIgnore @Schema(example = "data-db") private String host; + @JsonIgnore @Schema(example = "3306") private Integer port; - @JsonProperty("ui_host") - @Schema(example = "example.com") - private String uiHost; - - @JsonProperty("ui_port") - @Schema(example = "3306") - private Integer uiPort; - @NotNull private ImageDto image; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java index f0f40dd38c..1e54da2978 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java @@ -28,6 +28,11 @@ public class ViewDto extends CacheableDto { @Schema(example = "787439d0-e85e-400c-a7e6-996a023bfad9") private UUID id; + @NotNull + @JsonProperty("database_id") + @Schema(example = "fc29f89c-86a8-4020-9e36-4d954736c6cc") + private UUID databaseId; + @NotBlank @Schema(example = "Air Quality") private String name; @@ -61,10 +66,6 @@ public class ViewDto extends CacheableDto { @Schema(example = "7de03e818900b6ea6d58ad0306d4a741d658c6df3d1964e89ed2395d8c7e7916") private String queryHash; - @ToString.Exclude - @EqualsAndHashCode.Exclude - private DatabaseDto database; - @NotNull private UserBriefDto owner; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java index 4a0376e0ea..24915a3dd5 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/QueryDto.java @@ -29,6 +29,11 @@ public class QueryDto { @Schema(example = "83ea2326-f8f6-4263-baf8-cdf88a54efc7") private UUID id; + @NotNull + @JsonProperty("database_id") + @Schema(example = "fc29f89c-86a8-4020-9e36-4d954736c6cc") + private UUID databaseId; + @NotNull private UserBriefDto owner; @@ -57,10 +62,6 @@ public class QueryDto { @Schema(example = "17e682f060b5f8e47ea04c5c4855908b0a5ad612022260fe50e11ecb0cc0ab76") private String queryHash; - @ToString.Exclude - @EqualsAndHashCode.Exclude - private DatabaseDto database; - @NotNull @JsonProperty("is_persisted") @Schema(example = "true") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java index cb58fab23c..3dde709183 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java @@ -37,8 +37,8 @@ public class TableDto extends CacheableDto { @NotNull @JsonProperty("database_id") - @Schema(example = "692511b6-5af3-4043-8b9b-626af8756d92") - private UUID tdbid; + @Schema(example = "fc29f89c-86a8-4020-9e36-4d954736c6cc") + private UUID databaseId; @NotBlank @Schema(example = "Air Quality") @@ -109,10 +109,6 @@ public class TableDto extends CacheableDto { @NotNull private List<ColumnDto> columns; - @ToString.Exclude - @EqualsAndHashCode.Exclude - private DatabaseDto database; - @NotNull private ConstraintsDto constraints; diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java index ad1ef9cf25..2d18ca0c49 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -563,17 +563,13 @@ public interface MetadataMapper { .name(data.getName()) .internalName(data.getInternalName()) .owner(userToUserBriefDto(data.getOwner())) - .tdbid(data.getTdbid()) + .databaseId(data.getTdbid()) .isPublic(data.getIsPublic()) .isSchemaPublic(data.getIsSchemaPublic()) .isVersioned(true) .description(data.getDescription()) .identifiers(new LinkedList<>()) .columns(new LinkedList<>()) - .database(databaseToDatabaseDto(data.getDatabase() - .toBuilder() - .tables(null) - .build())) .constraints(constraintsToConstraintsDto(data.getConstraints())) .build(); if (data.getIdentifiers() != null) { @@ -600,15 +596,15 @@ public interface MetadataMapper { table.getConstraints() .getForeignKeys() .forEach(fk -> { - fk.getTable().setDatabaseId(table.getTdbid()); - fk.getReferencedTable().setDatabaseId(table.getTdbid()); + fk.getTable().setDatabaseId(table.getDatabaseId()); + fk.getReferencedTable().setDatabaseId(table.getDatabaseId()); fk.getReferences() .forEach(ref -> { ref.setForeignKey(foreignKeyDtoToForeignKeyBriefDto(fk)); ref.getColumn().setTableId(table.getId()); - ref.getColumn().setDatabaseId(table.getTdbid()); + ref.getColumn().setDatabaseId(table.getDatabaseId()); ref.getReferencedColumn().setTableId(fk.getReferencedTable().getId()); - ref.getReferencedColumn().setDatabaseId(table.getTdbid()); + ref.getReferencedColumn().setDatabaseId(table.getDatabaseId()); }); }); table.getConstraints() @@ -822,6 +818,9 @@ public interface MetadataMapper { .trim(); } + @Mappings({ + @Mapping(target = "databaseId", source = "database.id") + }) ViewDto viewToViewDto(View data); @Mappings({ diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index d2ccae77e6..f04f66eb8e 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -17,7 +17,6 @@ import at.tuwien.service.*; import at.tuwien.validation.EndpointValidator; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -28,7 +27,6 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -442,9 +440,6 @@ public class TableEndpoint extends AbstractEndpoint { @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Find table successfully", - headers = {@Header(name = "X-Username", description = "The authentication username", schema = @Schema(implementation = String.class)), - @Header(name = "X-Password", description = "The authentication password", schema = @Schema(implementation = String.class)), - @Header(name = "Access-Control-Expose-Headers", description = "Expose custom headers", schema = @Schema(implementation = String.class))}, content = {@Content( mediaType = "application/json", schema = @Schema(implementation = TableDto.class))}), @@ -486,13 +481,7 @@ public class TableEndpoint extends AbstractEndpoint { table.setConstraints(null); } final TableDto dto = metadataMapper.tableToTableDto(table); - final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Username", table.getDatabase().getContainer().getPrivilegedUsername()); - headers.set("X-Password", table.getDatabase().getContainer().getPrivilegedPassword()); - headers.set("X-Jdbc-Method", table.getDatabase().getContainer().getImage().getJdbcMethod()); - headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Jdbc-Method"); return ResponseEntity.ok() - .headers(headers) .body(dto); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 9871fb306c..432b84d50f 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -15,7 +15,6 @@ import at.tuwien.service.UserService; import at.tuwien.service.ViewService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -26,7 +25,6 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -173,14 +171,6 @@ public class ViewEndpoint extends AbstractEndpoint { @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Find view successfully", - headers = {@Header(name = "X-Username", description = "The authentication username", schema = @Schema(implementation = String.class)), - @Header(name = "X-Password", description = "The authentication password", schema = @Schema(implementation = String.class)), - @Header(name = "X-Host", description = "The database hostname", schema = @Schema(implementation = String.class)), - @Header(name = "X-Port", description = "The database port number", schema = @Schema(implementation = Integer.class)), - @Header(name = "X-Type", description = "The JDBC connection type", schema = @Schema(implementation = String.class)), - @Header(name = "X-Database", description = "The database internal name", schema = @Schema(implementation = String.class)), - @Header(name = "X-View", description = "The view internal name", schema = @Schema(implementation = String.class)), - @Header(name = "Access-Control-Expose-Headers", description = "Expose custom headers", schema = @Schema(implementation = String.class))}, content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ViewDto.class))}), @@ -202,20 +192,7 @@ public class ViewEndpoint extends AbstractEndpoint { log.debug("endpoint find view, databaseId={}, viewId={}", databaseId, viewId); final Database database = databaseService.findById(databaseId); final View view = viewService.findById(database, viewId); - final HttpHeaders headers = new HttpHeaders(); - if (isSystem(principal)) { - headers.set("X-Username", database.getContainer().getPrivilegedUsername()); - headers.set("X-Password", database.getContainer().getPrivilegedPassword()); - headers.set("X-Host", database.getContainer().getHost()); - headers.set("X-Port", "" + database.getContainer().getPort()); - headers.set("X-Type", database.getContainer().getImage().getJdbcMethod()); - headers.set("X-Database", database.getInternalName()); - headers.set("X-View", view.getInternalName()); - headers.set("X-Jdbc-Method", view.getDatabase().getContainer().getImage().getJdbcMethod()); - headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-View X-Jdbc-Method"); - } return ResponseEntity.status(HttpStatus.OK) - .headers(headers) .body(metadataMapper.viewToViewDto(view)); } diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java index 129487d074..230aada37a 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java @@ -43,7 +43,6 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_1.setColumns(new LinkedList<>(TABLE_1_COLUMNS)); TABLE_1.setConstraints(TABLE_1_CONSTRAINTS); VIEW_1_DTO.setIdentifiers(VIEW_1_DTO_IDENTIFIERS); - VIEW_1_DTO.setDatabase(DATABASE_1_DTO); DATABASE_1.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_1, IDENTIFIER_2, IDENTIFIER_3, IDENTIFIER_4))); IDENTIFIER_1.setDatabase(DATABASE_1); IDENTIFIER_2.setDatabase(DATABASE_1); @@ -57,18 +56,12 @@ public abstract class AbstractUnitTest extends BaseTest { DATABASE_1_DTO.setViews(new LinkedList<>(List.of(VIEW_1_DTO, VIEW_2_DTO, VIEW_3_DTO))); TABLE_1_DTO.setColumns(new LinkedList<>(TABLE_1_COLUMNS_DTO)); TABLE_1_DTO.setConstraints(TABLE_1_CONSTRAINTS_DTO); - TABLE_1_PRIVILEGED_DTO.setDatabase(DATABASE_1_DTO); - TABLE_1_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_1_COLUMNS_DTO)); - TABLE_1_PRIVILEGED_DTO.setConstraints(TABLE_1_CONSTRAINTS_DTO); TABLE_2.setDatabase(DATABASE_1); TABLE_2.setColumns(new LinkedList<>(TABLE_2_COLUMNS)); TABLE_2_CONSTRAINTS.getForeignKeys().get(0).getReferences().get(0).setForeignKey(TABLE_2_CONSTRAINTS.getForeignKeys().get(0)); TABLE_2.setConstraints(TABLE_2_CONSTRAINTS); TABLE_2_DTO.setColumns(new LinkedList<>(TABLE_2_COLUMNS_DTO)); TABLE_2_DTO.setConstraints(TABLE_2_CONSTRAINTS_DTO); - TABLE_2_PRIVILEGED_DTO.setDatabase(DATABASE_1_DTO); - TABLE_2_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_2_COLUMNS_DTO)); - TABLE_2_PRIVILEGED_DTO.setConstraints(TABLE_2_CONSTRAINTS_DTO); TABLE_3.setDatabase(DATABASE_1); TABLE_3.setColumns(new LinkedList<>(TABLE_3_COLUMNS)); TABLE_3.setConstraints(TABLE_3_CONSTRAINTS); @@ -79,21 +72,13 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_4.setConstraints(TABLE_4_CONSTRAINTS); TABLE_4_DTO.setColumns(TABLE_4_COLUMNS_DTO); TABLE_4_DTO.setConstraints(TABLE_4_CONSTRAINTS_DTO); - TABLE_4_PRIVILEGED_DTO.setDatabase(DATABASE_1_DTO); - TABLE_4_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_4_COLUMNS_DTO)); - TABLE_4_PRIVILEGED_DTO.setConstraints(TABLE_4_CONSTRAINTS_DTO); VIEW_1.setDatabase(DATABASE_1); VIEW_1.setColumns(new LinkedList<>(VIEW_1_COLUMNS)); VIEW_1.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_3))); - VIEW_1_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); VIEW_2.setDatabase(DATABASE_1); VIEW_2.setColumns(new LinkedList<>(VIEW_2_COLUMNS)); - VIEW_2_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); - VIEW_2_DTO.setDatabase(DATABASE_1_DTO); VIEW_3.setDatabase(DATABASE_1); VIEW_3.setColumns(new LinkedList<>(VIEW_3_COLUMNS)); - VIEW_3_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); - VIEW_3_DTO.setDatabase(DATABASE_1_DTO); IDENTIFIER_1.setDatabase(DATABASE_1); IDENTIFIER_2.setDatabase(DATABASE_1); IDENTIFIER_3.setDatabase(DATABASE_1); @@ -103,7 +88,6 @@ public abstract class AbstractUnitTest extends BaseTest { DATABASE_2.setAccesses(new LinkedList<>(List.of(DATABASE_2_USER_2_WRITE_ALL_ACCESS, DATABASE_2_USER_3_READ_ACCESS))); DATABASE_2.setTables(new LinkedList<>(List.of(TABLE_5, TABLE_6, TABLE_7))); VIEW_4.setColumns(new LinkedList<>(VIEW_4_COLUMNS)); - VIEW_4_DTO.setDatabase(DATABASE_2_DTO); DATABASE_2.setViews(new LinkedList<>(List.of(VIEW_4))); DATABASE_2.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_5))); DATABASE_2_DTO.setAccesses(new LinkedList<>(List.of(DATABASE_2_USER_2_WRITE_ALL_ACCESS_DTO, DATABASE_2_USER_3_READ_ACCESS_DTO))); @@ -119,7 +103,6 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_5.setConstraints(TABLE_5_CONSTRAINTS); TABLE_5_DTO.setColumns(new LinkedList<>(TABLE_5_COLUMNS_DTO)); TABLE_5_DTO.setConstraints(TABLE_5_CONSTRAINTS_DTO); - TABLE_5_PRIVILEGED_DTO.setDatabase(DATABASE_2_DTO); TABLE_6.setDatabase(DATABASE_2); TABLE_6.setColumns(new LinkedList<>(TABLE_6_COLUMNS)); TABLE_6.setConstraints(TABLE_6_CONSTRAINTS); @@ -153,14 +136,10 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_8.setConstraints(TABLE_8_CONSTRAINTS); TABLE_8_DTO.setColumns(new LinkedList<>(TABLE_8_COLUMNS_DTO)); TABLE_8_DTO.setConstraints(TABLE_8_CONSTRAINTS_DTO); - TABLE_8_PRIVILEGED_DTO.setColumns(new LinkedList<>(TABLE_8_COLUMNS_DTO)); - TABLE_8_PRIVILEGED_DTO.setDatabase(DATABASE_3_DTO); VIEW_5.setDatabase(DATABASE_3); VIEW_5.setColumns(VIEW_5_COLUMNS); VIEW_5_DTO.setColumns(VIEW_5_COLUMNS_DTO); - VIEW_5_DTO.setDatabase(DATABASE_3_DTO); IDENTIFIER_6.setDatabase(DATABASE_3); - QUERY_9_DTO.setDatabase(DATABASE_3_DTO); /* DATABASE 4 */ DATABASE_4.setSubsets(new LinkedList<>()); DATABASE_4.setAccesses(new LinkedList<>(List.of(DATABASE_4_USER_1_READ_ACCESS, DATABASE_4_USER_2_WRITE_OWN_ACCESS, DATABASE_4_USER_3_WRITE_ALL_ACCESS))); diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java index 25db961f77..c39cafae31 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java @@ -1521,29 +1521,6 @@ public abstract class BaseTest { public static final Instant TABLE_1_CREATED = Instant.ofEpochSecond(1677399975L) /* 2023-02-26 08:26:15 (UTC) */; public static final Instant TABLE_1_LAST_MODIFIED = Instant.ofEpochSecond(1677399975L) /* 2023-02-26 08:26:15 (UTC) */; - public static final TableDto TABLE_1_PRIVILEGED_DTO = TableDto.builder() - .id(TABLE_1_ID) - .tdbid(DATABASE_1_ID) - .internalName(TABLE_1_INTERNAL_NAME) - .isVersioned(TABLE_1_VERSIONED) - .isPublic(TABLE_1_SCHEMA_PUBLIC) - .description(TABLE_1_DESCRIPTION) - .name(TABLE_1_NAME) - .queueName(TABLE_1_QUEUE_NAME) - .routingKey(TABLE_1_ROUTING_KEY) - .identifiers(new LinkedList<>()) - .columns(new LinkedList<>() /* TABLE_1_COLUMNS_DTO */) - .constraints(null) /* TABLE_1_CONSTRAINTS_DTO */ - .owner(USER_1_BRIEF_DTO) - .isPublic(DATABASE_1_PUBLIC) - .avgRowLength(TABLE_1_AVG_ROW_LENGTH) - .numRows(TABLE_1_NUM_ROWS) - .dataLength(TABLE_1_DATA_LENGTH) - .maxDataLength(TABLE_1_MAX_DATA_LENGTH) - .lastRetrieved(Instant.now()) - .database(null) /* DATABASE_1_PRIVILEGED_DTO */ - .build(); - public static final Table TABLE_1 = Table.builder() .id(TABLE_1_ID) .tdbid(DATABASE_1_ID) @@ -1570,7 +1547,7 @@ public abstract class BaseTest { public static final TableDto TABLE_1_DTO = TableDto.builder() .id(TABLE_1_ID) - .tdbid(DATABASE_1_ID) + .databaseId(DATABASE_1_ID) .internalName(TABLE_1_INTERNAL_NAME) .isVersioned(TABLE_1_VERSIONED) .isPublic(TABLE_1_IS_PUBLIC) @@ -1745,32 +1722,9 @@ public abstract class BaseTest { .maxDataLength(TABLE_2_MAX_DATA_LENGTH) .build(); - public static final TableDto TABLE_2_PRIVILEGED_DTO = TableDto.builder() - .id(TABLE_2_ID) - .tdbid(DATABASE_1_ID) - .internalName(TABLE_2_INTERNALNAME) - .isVersioned(TABLE_2_VERSIONED) - .isPublic(TABLE_2_IS_PUBLIC) - .isSchemaPublic(TABLE_2_SCHEMA_PUBLIC) - .description(TABLE_2_DESCRIPTION) - .name(TABLE_2_NAME) - .queueName(TABLE_2_QUEUE_NAME) - .routingKey(TABLE_2_ROUTING_KEY) - .identifiers(new LinkedList<>()) - .columns(new LinkedList<>() /* TABLE_2_COLUMNS_DTO */) - .constraints(null) /* TABLE_2_CONSTRAINTS_DTO */ - .owner(USER_2_BRIEF_DTO) - .avgRowLength(TABLE_2_AVG_ROW_LENGTH) - .numRows(TABLE_2_NUM_ROWS) - .dataLength(TABLE_2_DATA_LENGTH) - .maxDataLength(TABLE_2_MAX_DATA_LENGTH) - .lastRetrieved(Instant.now()) - .database(null) /* DATABASE_1_PRIVILEGED_DTO */ - .build(); - public static final TableDto TABLE_2_DTO = TableDto.builder() .id(TABLE_2_ID) - .tdbid(DATABASE_1_ID) + .databaseId(DATABASE_1_ID) .internalName(TABLE_2_INTERNALNAME) .isVersioned(TABLE_2_VERSIONED) .isPublic(TABLE_2_IS_PUBLIC) @@ -1842,7 +1796,7 @@ public abstract class BaseTest { public static final TableDto TABLE_3_DTO = TableDto.builder() .id(TABLE_3_ID) - .tdbid(DATABASE_1_ID) + .databaseId(DATABASE_1_ID) .internalName(TABLE_3_INTERNALNAME) .isVersioned(TABLE_3_VERSIONED) .isPublic(TABLE_3_IS_PUBLIC) @@ -1941,7 +1895,7 @@ public abstract class BaseTest { public static final TableDto TABLE_5_DTO = TableDto.builder() .id(TABLE_5_ID) - .tdbid(DATABASE_2_ID) + .databaseId(DATABASE_2_ID) .internalName(TABLE_5_INTERNALNAME) .isVersioned(TABLE_5_VERSIONED) .isPublic(TABLE_5_IS_PUBLIC) @@ -1955,29 +1909,6 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final TableDto TABLE_5_PRIVILEGED_DTO = TableDto.builder() - .id(TABLE_5_ID) - .tdbid(DATABASE_2_ID) - .internalName(TABLE_5_INTERNALNAME) - .isVersioned(TABLE_5_VERSIONED) - .isPublic(TABLE_5_IS_PUBLIC) - .isSchemaPublic(TABLE_5_SCHEMA_PUBLIC) - .description(TABLE_5_DESCRIPTION) - .name(TABLE_5_NAME) - .queueName(TABLE_5_QUEUE_NAME) - .routingKey(TABLE_5_ROUTING_KEY) - .identifiers(new LinkedList<>()) - .columns(new LinkedList<>() /* TABLE_5_COLUMNS_DTO */) - .constraints(null) /* TABLE_5_CONSTRAINTS_DTO */ - .owner(USER_5_BRIEF_DTO) - .isPublic(DATABASE_2_PUBLIC) - .avgRowLength(TABLE_5_AVG_ROW_LENGTH) - .numRows(TABLE_5_NUM_ROWS) - .dataLength(TABLE_5_DATA_LENGTH) - .maxDataLength(TABLE_5_MAX_DATA_LENGTH) - .lastRetrieved(Instant.now()) - .build(); - public static final TableBriefDto TABLE_5_BRIEF_DTO = TableBriefDto.builder() .id(TABLE_5_ID) .databaseId(DATABASE_2_ID) @@ -2024,7 +1955,7 @@ public abstract class BaseTest { public static final TableDto TABLE_6_DTO = TableDto.builder() .id(TABLE_6_ID) - .tdbid(DATABASE_2_ID) + .databaseId(DATABASE_2_ID) .internalName(TABLE_6_INTERNALNAME) .isVersioned(TABLE_6_VERSIONED) .isPublic(TABLE_6_IS_PUBLIC) @@ -2084,7 +2015,7 @@ public abstract class BaseTest { public static final TableDto TABLE_7_DTO = TableDto.builder() .id(TABLE_7_ID) - .tdbid(DATABASE_2_ID) + .databaseId(DATABASE_2_ID) .internalName(TABLE_7_INTERNAL_NAME) .isVersioned(TABLE_7_VERSIONED) .isPublic(TABLE_7_IS_PUBLIC) @@ -2151,33 +2082,12 @@ public abstract class BaseTest { public static final TableDto TABLE_4_DTO = TableDto.builder() .id(TABLE_4_ID) - .tdbid(DATABASE_1_ID) - .internalName(TABLE_4_INTERNALNAME) - .description(TABLE_4_DESCRIPTION) - .name(TABLE_4_NAME) - .queueName(TABLE_4_QUEUE_NAME) - .routingKey(TABLE_4_ROUTING_KEY) - .columns(new LinkedList<>()) /* TABLE_4_COLUMNS_DTO */ - .constraints(null) /* TABLE_4_CONSTRAINTS_DTO */ - .isVersioned(TABLE_4_VERSIONED) - .isPublic(TABLE_4_IS_PUBLIC) - .isSchemaPublic(TABLE_4_SCHEMA_PUBLIC) - .owner(USER_1_BRIEF_DTO) - .avgRowLength(TABLE_4_AVG_ROW_LENGTH) - .numRows(TABLE_4_NUM_ROWS) - .dataLength(TABLE_4_DATA_LENGTH) - .maxDataLength(TABLE_4_MAX_DATA_LENGTH) - .build(); - - public static final TableDto TABLE_4_PRIVILEGED_DTO = TableDto.builder() - .id(TABLE_4_ID) - .tdbid(DATABASE_1_ID) + .databaseId(DATABASE_1_ID) .internalName(TABLE_4_INTERNALNAME) .description(TABLE_4_DESCRIPTION) .name(TABLE_4_NAME) .queueName(TABLE_4_QUEUE_NAME) .routingKey(TABLE_4_ROUTING_KEY) - .database(null) /* DATABASE_1_DTO */ .columns(new LinkedList<>()) /* TABLE_4_COLUMNS_DTO */ .constraints(null) /* TABLE_4_CONSTRAINTS_DTO */ .isVersioned(TABLE_4_VERSIONED) @@ -2188,7 +2098,6 @@ public abstract class BaseTest { .numRows(TABLE_4_NUM_ROWS) .dataLength(TABLE_4_DATA_LENGTH) .maxDataLength(TABLE_4_MAX_DATA_LENGTH) - .lastRetrieved(Instant.now()) .build(); public static final TableBriefDto TABLE_4_BRIEF_DTO = TableBriefDto.builder() @@ -2319,7 +2228,7 @@ public abstract class BaseTest { public static final TableDto TABLE_8_DTO = TableDto.builder() .id(TABLE_8_ID) - .tdbid(DATABASE_3_ID) + .databaseId(DATABASE_3_ID) .internalName(TABLE_8_INTERNAL_NAME) .description(TABLE_8_DESCRIPTION) .isVersioned(TABLE_8_VERSIONED) @@ -2350,22 +2259,6 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .build(); - public static final TableDto TABLE_8_PRIVILEGED_DTO = TableDto.builder() - .id(TABLE_8_ID) - .tdbid(DATABASE_3_ID) - .internalName(TABLE_8_INTERNAL_NAME) - .description(TABLE_8_DESCRIPTION) - .isVersioned(TABLE_8_VERSIONED) - .isPublic(TABLE_8_IS_PUBLIC) - .isSchemaPublic(TABLE_8_SCHEMA_PUBLIC) - .name(TABLE_8_NAME) - .queueName(TABLE_8_QUEUE_NAME) - .columns(new LinkedList<>()) /* TABLE_8_COLUMNS_DTO */ - .owner(USER_1_BRIEF_DTO) - .isPublic(DATABASE_3_PUBLIC) - .lastRetrieved(Instant.now()) - .build(); - public static final UUID TABLE_9_ID = UUID.fromString("9314294f-04fc-4354-8b1f-2a8aeb566453"); public static final String TABLE_9_NAME = "Weather Location"; public static final String TABLE_9_INTERNAL_NAME = "weather_location"; @@ -2400,7 +2293,7 @@ public abstract class BaseTest { public static final TableDto TABLE_9_DTO = TableDto.builder() .id(TABLE_9_ID) - .tdbid(DATABASE_4_ID) + .databaseId(DATABASE_4_ID) .internalName(TABLE_9_INTERNAL_NAME) .description(TABLE_9_DESCRIPTION) .isVersioned(TABLE_9_VERSIONED) @@ -2425,22 +2318,6 @@ public abstract class BaseTest { .ownedBy(USER_1_ID) .build(); - public static final TableDto TABLE_9_PRIVILEGED_DTO = TableDto.builder() - .id(TABLE_9_ID) - .tdbid(DATABASE_4_ID) - .internalName(TABLE_9_INTERNAL_NAME) - .description(TABLE_9_DESCRIPTION) - .isVersioned(TABLE_9_VERSIONED) - .isPublic(TABLE_9_IS_PUBLIC) - .isSchemaPublic(TABLE_9_SCHEMA_PUBLIC) - .name(TABLE_9_NAME) - .queueName(TABLE_9_QUEUE_NAME) - .columns(new LinkedList<>()) /* TABLE_9_COLUMNS_DTO */ - .owner(USER_1_BRIEF_DTO) - .isPublic(DATABASE_3_PUBLIC) - .lastRetrieved(Instant.now()) - .build(); - public static final UUID COLUMN_9_1_ID = UUID.fromString("e03c7578-2d1a-4599-9b11-7174f40efc0a"); public static final String COLUMN_9_1_NAME = "location"; public static final String COLUMN_9_1_INTERNAL_NAME = "location"; @@ -2565,6 +2442,7 @@ public abstract class BaseTest { public static final QueryDto QUERY_9_DTO = QueryDto.builder() .id(QUERY_9_ID) + .databaseId(DATABASE_3_ID) .query(QUERY_9_STATEMENT) .queryNormalized(QUERY_9_STATEMENT) .resultNumber(QUERY_9_RESULT_NUMBER) @@ -2573,7 +2451,6 @@ public abstract class BaseTest { .execution(QUERY_9_EXECUTION) .isPersisted(QUERY_9_PERSISTED) .owner(USER_1_BRIEF_DTO) - .database(DATABASE_3_DTO) .build(); public static final SubsetDto QUERY_9_SUBSET_DTO = SubsetDto.builder() @@ -3006,6 +2883,7 @@ public abstract class BaseTest { public static final QueryDto QUERY_4_DTO = QueryDto.builder() .id(QUERY_4_ID) + .databaseId(DATABASE_3_ID) .query(QUERY_4_STATEMENT) .queryNormalized(QUERY_4_STATEMENT) .resultNumber(QUERY_4_RESULT_NUMBER) @@ -3014,7 +2892,6 @@ public abstract class BaseTest { .execution(QUERY_4_EXECUTION) .isPersisted(QUERY_4_PERSISTED) .owner(USER_1_BRIEF_DTO) - .database(DATABASE_3_DTO) .build(); public static final UUID QUERY_5_ID = UUID.fromString("1a39f775-e3d5-4865-b4f5-dbbb5693b637"); @@ -3029,6 +2906,7 @@ public abstract class BaseTest { public static final QueryDto QUERY_5_DTO = QueryDto.builder() .id(QUERY_5_ID) + .databaseId(DATABASE_3_ID) .query(QUERY_5_STATEMENT) .queryNormalized(QUERY_5_STATEMENT) .resultNumber(QUERY_5_RESULT_NUMBER) @@ -3037,7 +2915,6 @@ public abstract class BaseTest { .execution(QUERY_5_EXECUTION) .isPersisted(QUERY_5_PERSISTED) .owner(USER_1_BRIEF_DTO) - .database(DATABASE_3_DTO) .build(); public static final SubsetDto QUERY_5_SUBSET_DTO = SubsetDto.builder() @@ -5130,7 +5007,6 @@ public abstract class BaseTest { public static final ViewDto VIEW_1_DTO = ViewDto.builder() .id(VIEW_1_ID) - .database(null) /* DATABASE_1_DTO */ .isInitialView(VIEW_1_INITIAL_VIEW) .name(VIEW_1_NAME) .internalName(VIEW_1_INTERNAL_NAME) @@ -5143,20 +5019,6 @@ public abstract class BaseTest { .columns(VIEW_1_COLUMNS_DTO) .build(); - public static final ViewDto VIEW_1_PRIVILEGED_DTO = ViewDto.builder() - .id(VIEW_1_ID) - .isInitialView(VIEW_1_INITIAL_VIEW) - .name(VIEW_1_NAME) - .internalName(VIEW_1_INTERNAL_NAME) - .isPublic(VIEW_1_PUBLIC) - .owner(USER_1_BRIEF_DTO) - .query(VIEW_1_QUERY) - .queryHash(VIEW_1_QUERY_HASH) - .columns(VIEW_1_COLUMNS_DTO) - .lastRetrieved(Instant.now()) - .database(null) /* DATABASE_1_PRIVILEGED_DTO */ - .build(); - public static final ViewBriefDto VIEW_1_BRIEF_DTO = ViewBriefDto.builder() .id(VIEW_1_ID) .isInitialView(VIEW_1_INITIAL_VIEW) @@ -5298,7 +5160,6 @@ public abstract class BaseTest { public static final ViewDto VIEW_2_DTO = ViewDto.builder() .id(VIEW_2_ID) - .database(null) /* DATABASE_1_DTO */ .isInitialView(VIEW_2_INITIAL_VIEW) .name(VIEW_2_NAME) .internalName(VIEW_2_INTERNAL_NAME) @@ -5310,21 +5171,6 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .build(); - public static final ViewDto VIEW_2_PRIVILEGED_DTO = ViewDto.builder() - .id(VIEW_2_ID) - .isInitialView(VIEW_2_INITIAL_VIEW) - .name(VIEW_2_NAME) - .internalName(VIEW_2_INTERNAL_NAME) - .isPublic(VIEW_2_PUBLIC) - .isSchemaPublic(VIEW_2_SCHEMA_PUBLIC) - .owner(USER_2_BRIEF_DTO) - .query(VIEW_2_QUERY) - .queryHash(VIEW_2_QUERY_HASH) - .columns(VIEW_2_COLUMNS_DTO) - .lastRetrieved(Instant.now()) - .database(null) /* DATABASE_1_PRIVILEGED_DTO */ - .build(); - public static final ViewBriefDto VIEW_2_BRIEF_DTO = ViewBriefDto.builder() .id(VIEW_2_ID) .isInitialView(VIEW_2_INITIAL_VIEW) @@ -5416,21 +5262,6 @@ public abstract class BaseTest { .database(null) /* DATABASE_1 */ .build(); - public static final ViewDto VIEW_3_PRIVILEGED_DTO = ViewDto.builder() - .id(VIEW_3_ID) - .isInitialView(VIEW_3_INITIAL_VIEW) - .name(VIEW_3_NAME) - .internalName(VIEW_3_INTERNAL_NAME) - .isPublic(VIEW_3_PUBLIC) - .isSchemaPublic(VIEW_3_SCHEMA_PUBLIC) - .owner(USER_1_BRIEF_DTO) - .query(VIEW_3_QUERY) - .queryHash(VIEW_3_QUERY_HASH) - .columns(VIEW_3_COLUMNS_DTO) - .lastRetrieved(Instant.now()) - .database(null) /* DATABASE_1_PRIVILEGED_DTO */ - .build(); - public static final List<ViewColumn> VIEW_3_COLUMNS = List.of( ViewColumn.builder() .id(VIEW_COLUMN_3_1_ID) @@ -5477,7 +5308,6 @@ public abstract class BaseTest { public static final ViewDto VIEW_3_DTO = ViewDto.builder() .id(VIEW_3_ID) - .database(null) /* DATABASE_1_DTO */ .isInitialView(VIEW_3_INITIAL_VIEW) .name(VIEW_3_NAME) .internalName(VIEW_3_INTERNAL_NAME) @@ -5683,7 +5513,6 @@ public abstract class BaseTest { public static final ViewDto VIEW_4_DTO = ViewDto.builder() .id(VIEW_4_ID) - .database(null) /* DATABASE_2_DTO */ .isInitialView(VIEW_4_INITIAL_VIEW) .name(VIEW_4_NAME) .internalName(VIEW_4_INTERNAL_NAME) @@ -5888,7 +5717,6 @@ public abstract class BaseTest { public static final ViewDto VIEW_5_DTO = ViewDto.builder() .id(VIEW_5_ID) - .database(null) /* DATABASE_3_DTO */ .isInitialView(VIEW_5_INITIAL_VIEW) .name(VIEW_5_NAME) .internalName(VIEW_5_INTERNAL_NAME) @@ -8372,6 +8200,7 @@ public abstract class BaseTest { public static final QueryDto QUERY_1_DTO = QueryDto.builder() .id(QUERY_1_ID) + .databaseId(DATABASE_1_ID) .query(QUERY_1_STATEMENT) .queryHash(QUERY_1_QUERY_HASH) .resultHash(QUERY_1_RESULT_HASH) @@ -8379,11 +8208,11 @@ public abstract class BaseTest { .owner(USER_1_BRIEF_DTO) .isPersisted(QUERY_1_PERSISTED) .resultNumber(3L) - .database(DATABASE_1_DTO) .build(); public static final QueryDto QUERY_2_DTO = QueryDto.builder() .id(QUERY_2_ID) + .databaseId(DATABASE_1_ID) .query(QUERY_2_STATEMENT) .queryNormalized(QUERY_2_STATEMENT) .resultNumber(QUERY_2_RESULT_NUMBER) @@ -8393,11 +8222,11 @@ public abstract class BaseTest { .execution(QUERY_2_EXECUTION) .isPersisted(QUERY_2_PERSISTED) .resultNumber(3L) - .database(DATABASE_1_DTO) .build(); public static final QueryDto QUERY_3_DTO = QueryDto.builder() .id(QUERY_3_ID) + .databaseId(DATABASE_1_ID) .query(QUERY_3_STATEMENT) .queryNormalized(QUERY_3_STATEMENT) .resultNumber(QUERY_3_RESULT_NUMBER) @@ -8407,11 +8236,11 @@ public abstract class BaseTest { .execution(QUERY_3_EXECUTION) .isPersisted(QUERY_3_PERSISTED) .resultNumber(2L) - .database(DATABASE_1_DTO) .build(); public static final QueryDto QUERY_7_DTO = QueryDto.builder() .id(QUERY_7_ID) + .databaseId(DATABASE_4_ID) .query(QUERY_7_STATEMENT) .queryNormalized(QUERY_7_STATEMENT) .resultNumber(QUERY_7_RESULT_NUMBER) @@ -8421,11 +8250,11 @@ public abstract class BaseTest { .execution(QUERY_7_EXECUTION) .isPersisted(QUERY_7_PERSISTED) .resultNumber(2L) - .database(DATABASE_4_DTO) .build(); public static final QueryDto QUERY_6_DTO = QueryDto.builder() .id(QUERY_6_ID) + .databaseId(DATABASE_1_ID) .query(QUERY_6_STATEMENT) .queryNormalized(QUERY_6_STATEMENT) .resultNumber(QUERY_6_RESULT_NUMBER) @@ -8434,11 +8263,11 @@ public abstract class BaseTest { .queryHash(QUERY_6_QUERY_HASH) .execution(QUERY_6_EXECUTION) .isPersisted(QUERY_6_PERSISTED) - .database(DATABASE_1_DTO) .build(); public static final QueryDto QUERY_8_DTO = QueryDto.builder() .id(QUERY_8_ID) + .databaseId(DATABASE_2_ID) .query(QUERY_8_STATEMENT) .queryNormalized(QUERY_8_STATEMENT) .resultNumber(QUERY_8_RESULT_NUMBER) @@ -8448,7 +8277,6 @@ public abstract class BaseTest { .execution(QUERY_8_EXECUTION) .isPersisted(QUERY_8_PERSISTED) .resultNumber(3L) - .database(DATABASE_2_DTO) .build(); } diff --git a/helm/dbrepo/files/create-event-listener.jar b/helm/dbrepo/files/create-event-listener.jar index a9ba91e5a9968aa8bf870cde04069870cf365960..1d72200c19c7b9fb124773e3ffc0249d1b535e2f 100644 GIT binary patch delta 712 zcmbQ^KgVAvz?+#xgn@yBgMlw8DJoWZ(WZ$)O7#bW4jBmSEnoJ3g1iUQmTfm?KX8=1 zASv)ZbJJ9w+*_X8T>sq**wWLpSZ-3zCjH-W_tI2*^bRQ2vc4|KH8M(DY%n8QfTQbN zpJZewAJ5LsMa!)>s3d*lG|Vnt`NHY#%Vmr&*Dp;h=qg#b)FHleUxtpNvexzsS3<Vz zSj?BRTs20yp8cI?{4cA_kX++UGp?SS_{Zbgf)mXL3@X;l64EmGVSZoqi?rhIpNjwe z&%LdhIZ-z0vC%pHcIL~i$v5OoB-B)dPi)m(Q;-qext8_#`A-!R6^n)U>$s@1?W;bq z)!^{MaQ8i1&-cx<njjdsQsv!u|3#n9$7WsL_x(5He1rSWQoS$h)ytH%t=9K4cGliI zsa1XX2LHLgd$NnwUU$8JsBt>#O?$&nmFa)u7hI@3`|shFD|`nVY{lc8m!IFF&|M+Y zKl!D})Ih7C%sF@5ge6X!oOAS1&tlrywfyDJd)KCkKd-xd;3Ct9Q`H>b7A+Nj#9Ev6 z(XH(uJ18Ew7#KJhK=CknBclp4Z&K3a8;rWld`U@@Ihf?Yv?h}(m=0vp0@HO&CSZCi zlNVS$6Z2UxeTlgnB)<7S8#gDIk-##C3C!RXs1XD)Cif`L0@IpGlR02fKlzA~6<Cl_ z*#vBkg|aP}U!klArdKMPg6W6K5Os1YE?|DDN)%ZAA(db-EuosL05X*OpWvTc91INW z1Q-~^7!Y7dV=&8PK6Z)8vT8hFh5tV_@AhY6V7SK0z+i+>$FQU^k#}-Fi^=4hsytwu Rbkuf%>6dC5U^+zI0{~|C6Mp~z delta 690 zcmbQ^KgVAvz?+#xgn@yBgCV3bG3xYJlh}zuO7*_MhZO|&rmOvLv}ah7dF#rZHF8@X zANSdMZ~KOgKEjt8eY5`WHMwe0Ci9g+=S}kc$GYDWd^_j;;I_(_irz5M<I#&#iUL`7 z_9AcOthT(lw6gc*g^e3e^mSBbYn>IZIz7K^#i6Y>eSH%(dzrYV{@A>bi+kC1zH;97 zX=Zm8zwS9yT>s?2+;2<IPYyF*m(X4L*fv`JhLGuQ#;(P;tHKj|r~P|o-CU<EGFkr9 z|0glJ@42=q-umfu>TjLC&r8;=)y-iILJpU1TxwLmu9YQQRXIuhv4(^#?`bA0i683< za}V&f&zI%AW>;1B#^K<CYnRvDw|9`8SDl{o``UZ<KOrr0pFVcf*C)&mIlEpeJ1}tm z_f>jvykDJ98RXyE8sMwDy&@o#`L?2fqGsrSaf>p?;tGrPJ?dLt__a>IF;h5qX1~zV z&pO_dI%h4J@ysAt+|%mXW|@H0%`66I)qcLbcPcdg+}~x6lbolNeh|1jeOjD{z?X%p z5|ZxkLGi%Fz`(%(iigP?8C95r8WShqVAN#}ZcLoa!6XN!HJMbILmCq&2Qq1a={hD8 zFuj$@3#^`r`7D^e#M}*1zd4V04ilJ>z{1T5X7CEs2!gfrD9!@Yno5&7U{OE$h>{gp zkWtwLY>tJpElAho3S~Voy;9i}EdNj$qE1f51<X%Xi2|!Xq!J9KB~)|4>d&Z3GX=9u zuH`kEEUU(&5Zss;#r;q4&n*rHhIIlA3}Orju%z)5+vI!}iOG9adBA#g)OLZ*eyNrL IrbE;{01wp~v;Y7A diff --git a/lib/python/dbrepo/api/dto.py b/lib/python/dbrepo/api/dto.py index 53b61015ff..59c8210c76 100644 --- a/lib/python/dbrepo/api/dto.py +++ b/lib/python/dbrepo/api/dto.py @@ -87,8 +87,6 @@ class Container(BaseModel): id: str name: str internal_name: str - host: str - port: int image: Image ui_host: Optional[str] = None ui_port: Optional[int] = None @@ -708,11 +706,11 @@ class View(BaseModel): id: str name: str query: str + database_id: str query_hash: str owner: UserBrief internal_name: str is_public: bool - database: DatabaseBrief is_schema_public: bool initial_view: bool columns: List[ViewColumn] diff --git a/lib/python/dbrepo/api/mapper.py b/lib/python/dbrepo/api/mapper.py index 7ab697a81c..c062b29923 100644 --- a/lib/python/dbrepo/api/mapper.py +++ b/lib/python/dbrepo/api/mapper.py @@ -12,7 +12,7 @@ def query_to_subset(database: Database, image: Image, query: QueryDefinition) -> column.internal_name in query.columns] if len(filtered_column_ids) != len(query.columns): raise MalformedError(f'Failed to create view: not all columns found in database') - filter = [] + filters = [] if query.filter is not None: for filter in query.filter: # column_id @@ -21,11 +21,13 @@ def query_to_subset(database: Database, image: Image, query: QueryDefinition) -> if len(filter_column_ids) != 1: raise MalformedError(f'Failed to create view: filtered column name not found in database') # operator_id - filter_ops_ids: [str] = [op for op in image.operators if op.value == filter.operator] + filter_ops_ids: [str] = [op.id for op in image.operators if op.value == filter.operator] if len(filter_ops_ids) != 1: raise MalformedError(f'Failed to create view: filter operator not found in image') - filter.append(Filter(type=filter.type, column_id=filter_column_ids[0].id, operator_id=filter_ops_ids[0].id, - value=filter.value)) + filters.append(Filter(type=filter.type, + column_id=filter_column_ids[0], + operator_id=filter_ops_ids[0], + value=filter.value)) order = None if query.order is not None: for order in query.order: @@ -35,4 +37,4 @@ def query_to_subset(database: Database, image: Image, query: QueryDefinition) -> if len(order_column_ids) != 1: raise MalformedError(f'Failed to create view: order column name not found in database') order.append(Order(column_id=order_column_ids[0].id, direction=order.direction)) - return Subset(table_id=tables[0].id, columns=filtered_column_ids, filter=filter, order=order) + return Subset(table_id=tables[0].id, columns=filtered_column_ids, filter=filters, order=order) diff --git a/lib/python/tests/test_unit_query.py b/lib/python/tests/test_unit_query.py index fb23a3c949..44f165b9b0 100644 --- a/lib/python/tests/test_unit_query.py +++ b/lib/python/tests/test_unit_query.py @@ -6,108 +6,257 @@ import requests_mock from pandas import DataFrame from dbrepo.RestClient import RestClient -from dbrepo.api.dto import Query, QueryType, UserBrief +from dbrepo.api.dto import Query, QueryType, UserBrief, QueryDefinition, FilterDefinition, FilterType, Database, \ + ContainerBrief, ImageBrief, Image, Table, Constraints, PrimaryKey, TableBrief, ColumnBrief, ColumnType, \ + Column, Operator from dbrepo.api.exceptions import MalformedError, NotExistsError, ForbiddenError, QueryStoreError, FormatNotAvailable, \ ServiceError, ResponseCodeError, AuthenticationError class QueryUnitTest(unittest.TestCase): + database = Database( + id="6bd39359-b154-456d-b9c2-caa516a45732", + name='test', + owner=UserBrief(id='abdbf897-e599-4e5a-a3f0-7529884ea011', username='mweise'), + contact=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise'), + exchange_name='dbrepo', + internal_name='test_abcd', + is_public=True, + is_schema_public=True, + tables=[Table(id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", + name="Some Table", + description="Test Table", + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + internal_name="some_table", + owner=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise'), + is_versioned=True, + queue_name='test', + routing_key='dbrepo.test_database_1234.test', + is_public=True, + is_schema_public=True, + constraints=Constraints(uniques=[], + foreign_keys=[], + checks=[], + primary_key=[PrimaryKey(id="1516310f-ecb5-4614-abe2-3b96114e1484", + table=TableBrief( + id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + name='Other', + internal_name='other', + description=None, + is_versioned=True, + is_public=True, + is_schema_public=True, + owned_by='8638c043-5145-4be8-a3e4-4b79991b0a16'), + column=ColumnBrief( + id="31a533b6-8ddf-43d6-ac6a-b9da597cb976", + table_id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + name='id', + alias=None, + internal_name='id', + type=ColumnType.BIGINT))]), + columns=[Column(id="31a533b6-8ddf-43d6-ac6a-b9da597cb976", + name="ID", + ord=0, + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + table_id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", + internal_name="id", + type=ColumnType.BIGINT, + is_null_allowed=False), + Column(id="85de93a8-834c-4cf4-9d34-f80ebd97e606", + name="Username", + ord=1, + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + table_id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", + internal_name="username", + type=ColumnType.VARCHAR, + is_null_allowed=False) + ])], + container=ContainerBrief(id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", + name='MariaDB Galera 11.1.3', + internal_name='mariadb', + image=ImageBrief(id="b104648b-54d2-4d72-9834-8e0e6d428b39", + name='mariadb', + version='11.2.2', + default=True))) + image = Image(id="b104648b-54d2-4d72-9834-8e0e6d428b39", + name='mariadb', + version='11.2.2', + default=True, + data_types=[], + operators=[Operator(id="6a96bd99-be3d-4d56-8c38-b14bdfead634", + display_name="IN", + value="IN", + documentation="https://mariadb.com/kb/en/in/")]) def test_create_subset_succeeds(self): with requests_mock.Mocker() as mock: exp = [{'id': 1, 'username': 'foo'}, {'id': 2, 'username': 'bar'}] df = DataFrame.from_records(json.dumps(exp)) # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', json=json.dumps(exp), + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/subset', json=json.dumps(exp), headers={'X-Id': '1'}, status_code=201) # test client = RestClient(username="a", password="b") response = client.create_subset(database_id="6bd39359-b154-456d-b9c2-caa516a45732", page=0, size=10, timestamp=datetime.datetime(2024, 1, 1, 0, 0, 0, 0, datetime.timezone.utc), - query="SELECT id, username FROM some_table WHERE id IN (1,2)") + query=QueryDefinition(table="some_table", + columns=["id", "username"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) self.assertTrue(DataFrame.equals(df, response)) def test_create_subset_400_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', status_code=400) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/subset', status_code=400) # test try: client = RestClient(username="a", password="b") client.create_subset(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - query="SELECT id, username FROM some_table WHERE id IN (1,2)") + query=QueryDefinition(table="some_table", + columns=["id", "username"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except MalformedError: pass def test_create_subset_403_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', status_code=403) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/subset', status_code=403) # test try: client = RestClient(username="a", password="b") client.create_subset(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - query="SELECT id, username FROM some_table WHERE id IN (1,2)") + query=QueryDefinition(table="some_table", + columns=["id", "username"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except ForbiddenError: pass def test_create_subset_404_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', status_code=404) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/subset', status_code=404) # test try: client = RestClient(username="a", password="b") client.create_subset(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - query="SELECT id, username FROM some_table WHERE id IN (1,2)") + query=QueryDefinition(table="some_table", + columns=["id", "username"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except NotExistsError: pass def test_create_subset_417_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', status_code=417) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/subset', status_code=417) # test try: client = RestClient(username="a", password="b") client.create_subset(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - query="SELECT id, username FROM some_table WHERE id IN (1,2)") + query=QueryDefinition(table="some_table", + columns=["id", "username"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except QueryStoreError: pass def test_create_subset_501_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', status_code=501) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/subset', status_code=501) # test try: client = RestClient(username="a", password="b") client.create_subset(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - query="SELECT id, username FROM some_table WHERE id IN (1,2)") + query=QueryDefinition(table="some_table", + columns=["id", "username"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except FormatNotAvailable: pass def test_create_subset_503_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', status_code=503) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/subset', status_code=503) # test try: client = RestClient(username="a", password="b") client.create_subset(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - query="SELECT id, username FROM some_table WHERE id IN (1,2)") + query=QueryDefinition(table="some_table", + columns=["id", "username"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except ServiceError: pass def test_create_subset_unknown_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', status_code=200) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/subset', status_code=200) # test try: client = RestClient(username="a", password="b") client.create_subset(database_id="6bd39359-b154-456d-b9c2-caa516a45732", - query="SELECT id, username FROM some_table WHERE id IN (1,2)") + query=QueryDefinition(table="some_table", + columns=["id", "username"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except ResponseCodeError: pass @@ -116,13 +265,22 @@ class QueryUnitTest(unittest.TestCase): exp = [{'id': 1, 'username': 'foo'}, {'id': 2, 'username': 'bar'}] df = DataFrame.from_records(json.dumps(exp)) # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', json=json.dumps(exp), + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/subset', json=json.dumps(exp), headers={'X-Id': '1'}, status_code=201) # test client = RestClient() response = client.create_subset(database_id="6bd39359-b154-456d-b9c2-caa516a45732", page=0, size=10, - query="SELECT id, username FROM some_table WHERE id IN (1,2)") + query=QueryDefinition(table="some_table", + columns=["id", "username"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) self.assertTrue(DataFrame.equals(df, response)) def test_get_subset_succeeds(self): @@ -211,7 +369,7 @@ class QueryUnitTest(unittest.TestCase): with requests_mock.Mocker() as mock: exp = [] # mock - mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', json=[]) + mock.get(f'/api/database/{self.database.id}/subset', json=[]) # test response = RestClient().get_queries(database_id="6bd39359-b154-456d-b9c2-caa516a45732") self.assertEqual(exp, response) @@ -343,7 +501,7 @@ class QueryUnitTest(unittest.TestCase): result_number=None, identifiers=[])] # mock - mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', json=[exp[0].model_dump()]) + mock.get(f'/api/database/{self.database.id}/subset', json=[exp[0].model_dump()]) # test response = RestClient().get_queries(database_id="6bd39359-b154-456d-b9c2-caa516a45732") self.assertEqual(exp, response) @@ -351,7 +509,7 @@ class QueryUnitTest(unittest.TestCase): def test_get_queries_403_fails(self): with requests_mock.Mocker() as mock: # mock - mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', status_code=403) + mock.get(f'/api/database/{self.database.id}/subset', status_code=403) # test try: RestClient().get_queries(database_id="6bd39359-b154-456d-b9c2-caa516a45732") @@ -361,7 +519,7 @@ class QueryUnitTest(unittest.TestCase): def test_get_queries_404_fails(self): with requests_mock.Mocker() as mock: # mock - mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', status_code=404) + mock.get(f'/api/database/{self.database.id}/subset', status_code=404) # test try: RestClient().get_queries(database_id="6bd39359-b154-456d-b9c2-caa516a45732") @@ -371,7 +529,7 @@ class QueryUnitTest(unittest.TestCase): def test_get_queries_503_fails(self): with requests_mock.Mocker() as mock: # mock - mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', status_code=503) + mock.get(f'/api/database/{self.database.id}/subset', status_code=503) # test try: RestClient().get_queries(database_id="6bd39359-b154-456d-b9c2-caa516a45732") @@ -381,7 +539,7 @@ class QueryUnitTest(unittest.TestCase): def test_get_queries_unknown_fails(self): with requests_mock.Mocker() as mock: # mock - mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/subset', status_code=202) + mock.get(f'/api/database/{self.database.id}/subset', status_code=202) # test try: RestClient().get_queries(database_id="6bd39359-b154-456d-b9c2-caa516a45732") diff --git a/lib/python/tests/test_unit_view.py b/lib/python/tests/test_unit_view.py index 5792d028b3..cb26eeaba8 100644 --- a/lib/python/tests/test_unit_view.py +++ b/lib/python/tests/test_unit_view.py @@ -5,17 +5,94 @@ import requests_mock from pandas import DataFrame from dbrepo.RestClient import RestClient -from dbrepo.api.dto import View, ViewColumn, ColumnType, UserBrief, ViewBrief +from dbrepo.api.dto import View, ViewColumn, ColumnType, UserBrief, ViewBrief, QueryDefinition, FilterDefinition, \ + FilterType, Database, Table, Constraints, PrimaryKey, TableBrief, ColumnBrief, Column, ContainerBrief, ImageBrief, \ + Image, Operator from dbrepo.api.exceptions import ForbiddenError, NotExistsError, MalformedError, AuthenticationError, \ ResponseCodeError, ExternalSystemError, ServiceError, ServiceConnectionError class ViewUnitTest(unittest.TestCase): + database = Database( + id="6bd39359-b154-456d-b9c2-caa516a45732", + name='test', + owner=UserBrief(id='abdbf897-e599-4e5a-a3f0-7529884ea011', username='mweise'), + contact=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise'), + exchange_name='dbrepo', + internal_name='test_abcd', + is_public=True, + is_schema_public=True, + tables=[Table(id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", + name="Some Table", + description="Test Table", + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + internal_name="some_table", + owner=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise'), + is_versioned=True, + queue_name='test', + routing_key='dbrepo.test_database_1234.test', + is_public=True, + is_schema_public=True, + constraints=Constraints(uniques=[], + foreign_keys=[], + checks=[], + primary_key=[PrimaryKey(id="1516310f-ecb5-4614-abe2-3b96114e1484", + table=TableBrief( + id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + name='Other', + internal_name='other', + description=None, + is_versioned=True, + is_public=True, + is_schema_public=True, + owned_by='8638c043-5145-4be8-a3e4-4b79991b0a16'), + column=ColumnBrief( + id="31a533b6-8ddf-43d6-ac6a-b9da597cb976", + table_id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + name='id', + alias=None, + internal_name='id', + type=ColumnType.BIGINT))]), + columns=[Column(id="31a533b6-8ddf-43d6-ac6a-b9da597cb976", + name="ID", + ord=0, + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + table_id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", + internal_name="id", + type=ColumnType.BIGINT, + is_null_allowed=False), + Column(id="85de93a8-834c-4cf4-9d34-f80ebd97e606", + name="Username", + ord=1, + database_id="6bd39359-b154-456d-b9c2-caa516a45732", + table_id="029d773f-f98b-40c0-ab22-b8b1635d4fbc", + internal_name="username", + type=ColumnType.VARCHAR, + is_null_allowed=False) + ])], + container=ContainerBrief(id="44d811a8-4019-46ba-bd57-ea10a2eb0c74", + name='MariaDB Galera 11.1.3', + internal_name='mariadb', + image=ImageBrief(id="b104648b-54d2-4d72-9834-8e0e6d428b39", + name='mariadb', + version='11.2.2', + default=True))) + image = Image(id="b104648b-54d2-4d72-9834-8e0e6d428b39", + name='mariadb', + version='11.2.2', + default=True, + data_types=[], + operators=[Operator(id="6a96bd99-be3d-4d56-8c38-b14bdfead634", + display_name="IN", + value="IN", + documentation="https://mariadb.com/kb/en/in/")]) def test_get_views_empty_succeeds(self): with requests_mock.Mocker() as mock: # mock - mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', json=[]) + mock.get(f'/api/database/{self.database.id}/view', json=[]) # test response = RestClient().get_views(database_id="6bd39359-b154-456d-b9c2-caa516a45732") self.assertEqual([], response) @@ -33,7 +110,7 @@ class ViewUnitTest(unittest.TestCase): is_public=True, is_schema_public=True)] # mock - mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', json=[exp[0].model_dump()]) + mock.get(f'/api/database/{self.database.id}/view', json=[exp[0].model_dump()]) # test response = RestClient().get_views(database_id="6bd39359-b154-456d-b9c2-caa516a45732") self.assertEqual(exp, response) @@ -41,7 +118,7 @@ class ViewUnitTest(unittest.TestCase): def test_get_views_404_fails(self): with requests_mock.Mocker() as mock: # mock - mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', status_code=404) + mock.get(f'/api/database/{self.database.id}/view', status_code=404) # test try: response = RestClient().get_views(database_id="6bd39359-b154-456d-b9c2-caa516a45732") @@ -51,7 +128,7 @@ class ViewUnitTest(unittest.TestCase): def test_get_views_unknown_fails(self): with requests_mock.Mocker() as mock: # mock - mock.get('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', status_code=202) + mock.get(f'/api/database/{self.database.id}/view', status_code=202) # test try: response = RestClient().get_views(database_id="6bd39359-b154-456d-b9c2-caa516a45732") @@ -192,133 +269,207 @@ class ViewUnitTest(unittest.TestCase): def test_create_view_succeeds(self): with requests_mock.Mocker() as mock: - exp = View(id="1b3449d2-780e-4683-9af0-8733e608a4aa", + exp = ViewBrief(id="1b3449d2-780e-4683-9af0-8733e608a4aa", name="Data", internal_name="data", database_id="6bd39359-b154-456d-b9c2-caa516a45732", initial_view=False, - query="SELECT id FROM mytable WHERE deg > 0", + query="SELECT id FROM some_table WHERE id IN (1,2)", query_hash="94c74728b11a690e51d64719868824735f0817b7", - owner=UserBrief(id='8638c043-5145-4be8-a3e4-4b79991b0a16', username='mweise'), + owned_by='8638c043-5145-4be8-a3e4-4b79991b0a16', is_public=True, - is_schema_public=True, - columns=[ViewColumn(id="1b3449d2-780e-4683-9af0-8733e608a4aa", - ord=0, - name="id", - internal_name="id", - database_id="6bd39359-b154-456d-b9c2-caa516a45732", - type=ColumnType.BIGINT, - is_null_allowed=False)], - identifiers=[]) + is_schema_public=True) # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', json=exp.model_dump(), status_code=201) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/view', json=exp.model_dump(), status_code=201) # test client = RestClient(username="a", password="b") response = client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", is_public=True, is_schema_public=True, - query="SELECT id FROM mytable WHERE deg > 0") + query=QueryDefinition(table="some_table", + columns=["id"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) self.assertEqual(exp, response) def test_create_view_400_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', status_code=400) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/view', status_code=400) # test try: client = RestClient(username="a", password="b") - response = client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", - is_public=True, is_schema_public=True, - query="SELECT id FROM mytable WHERE deg > 0") + client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", + is_public=True, is_schema_public=True, + query=QueryDefinition(table="some_table", + columns=["id"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except MalformedError: pass def test_create_view_403_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', status_code=403) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/view', status_code=403) # test try: client = RestClient(username="a", password="b") - response = client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", - is_public=True, is_schema_public=True, - query="SELECT id FROM mytable WHERE deg > 0") + client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", + is_public=True, is_schema_public=True, + query=QueryDefinition(table="some_table", + columns=["id"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except ForbiddenError: pass def test_create_view_404_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', status_code=404) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/view', status_code=404) # test try: client = RestClient(username="a", password="b") - response = client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", - is_public=True, is_schema_public=True, - query="SELECT id FROM mytable WHERE deg > 0") + client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", + is_public=True, is_schema_public=True, + query=QueryDefinition(table="some_table", + columns=["id"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except NotExistsError: pass def test_create_view_423_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', status_code=423) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/view', status_code=423) # test try: client = RestClient(username="a", password="b") - response = client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", - is_public=True, is_schema_public=True, - query="SELECT id FROM mytable WHERE deg > 0") + client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", + is_public=True, is_schema_public=True, + query=QueryDefinition(table="some_table", + columns=["id"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except ExternalSystemError: pass def test_create_view_502_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', status_code=502) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/view', status_code=502) # test try: client = RestClient(username="a", password="b") - response = client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", - is_public=True, is_schema_public=True, - query="SELECT id FROM mytable WHERE deg > 0") + client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", + is_public=True, is_schema_public=True, + query=QueryDefinition(table="some_table", + columns=["id"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except ServiceConnectionError: pass def test_create_view_503_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', status_code=503) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/view', status_code=503) # test try: client = RestClient(username="a", password="b") - response = client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", - is_public=True, is_schema_public=True, - query="SELECT id FROM mytable WHERE deg > 0") + client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", + is_public=True, is_schema_public=True, + query=QueryDefinition(table="some_table", + columns=["id"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except ServiceError: pass def test_create_view_unknown_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', status_code=200) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/view', status_code=200) # test try: client = RestClient(username="a", password="b") - response = client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", - is_public=True, is_schema_public=True, - query="SELECT id FROM mytable WHERE deg > 0") + client.create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", + is_public=True, is_schema_public=True, + query=QueryDefinition(table="some_table", + columns=["id"], + filter=[FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except ResponseCodeError: pass def test_create_view_anonymous_fails(self): with requests_mock.Mocker() as mock: # mock - mock.post('/api/database/6bd39359-b154-456d-b9c2-caa516a45732/view', status_code=404) + mock.get(f'/api/image/{self.image.id}', json=self.image.model_dump(), + status_code=200) + mock.get(f'/api/database/{self.database.id}', json=self.database.model_dump(), + status_code=200) + mock.post(f'/api/database/{self.database.id}/view', status_code=404) # test try: - response = RestClient().create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", - is_public=True, is_schema_public=True, - query="SELECT id FROM mytable WHERE deg > 0") + RestClient().create_view(database_id="6bd39359-b154-456d-b9c2-caa516a45732", name="Data", + is_public=True, is_schema_public=True, + query=QueryDefinition(table="some_table", + columns=["id"], + filter=[ + FilterDefinition(type=FilterType.WHERE, + column="id", + operator="IN", + value="(1,2)")])) except AuthenticationError: pass -- GitLab From eeab268a92eb5d2a330fea22288a10b5a9f3e3de Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Sun, 2 Mar 2025 15:09:56 +0100 Subject: [PATCH 07/11] WIP Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- .docs/.openapi/api-data.yaml | 816 ++-- .docs/.openapi/api-metadata.yaml | 4001 ++++++++--------- .docs/.openapi/api.yaml | 3793 +++++++--------- .../tuwien/api/database/query/FilterDto.java | 2 +- .../tuwien/api/database/query/OrderDto.java | 2 +- .../table/columns/CreateTableColumnDto.java | 2 +- .../api/database/table/columns/EnumDto.java | 2 +- .../api/database/table/columns/SetDto.java | 2 +- .../foreign/CreateForeignKeyDto.java | 6 + .../api/identifier/IdentifierBriefDto.java | 2 +- lib/python/dbrepo/api/dto.py | 4 +- lib/python/tests/test_dtos.py | 5 +- 12 files changed, 4164 insertions(+), 4473 deletions(-) diff --git a/.docs/.openapi/api-data.yaml b/.docs/.openapi/api-data.yaml index bd14ba5505..24ace0b9bc 100644 --- a/.docs/.openapi/api-data.yaml +++ b/.docs/.openapi/api-data.yaml @@ -8,10 +8,10 @@ info: license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0 - version: 1.6.2 + version: 1.7.0 externalDocs: description: Sourcecode Documentation - url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6.2/system-services-metadata/ + url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7.0/system-services-metadata/ servers: - url: http://localhost description: Development instance @@ -24,22 +24,21 @@ paths: - view-endpoint summary: Get view data description: "Gets data from a view of a database. For private databases, the\ - \ user needs at least *READ* access to the associated database. Requires role\ - \ `view-database-view-data`." + \ user needs at least *READ* access to the associated database." operationId: getData parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: page in: query required: false @@ -59,32 +58,26 @@ paths: type: string format: date-time responses: - "503": - description: Failed to establish connection with the metadata service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "404": description: Failed to find view in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "409": - description: View schema could not be mapped + "403": + description: Not allowed to retrieve view data content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Request pagination is malformed + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Not allowed to retrieve view data + "400": + description: Request pagination is malformed content: application/json: schema: @@ -104,6 +97,12 @@ paths: application/json: schema: type: string + "409": + description: View schema could not be mapped + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - basicAuth: [] - bearerAuth: [] @@ -112,22 +111,21 @@ paths: - view-endpoint summary: Get view data description: "Gets data from a view of a database. For private databases, the\ - \ user needs at least *READ* access to the associated database. Requires role\ - \ `view-database-view-data`." + \ user needs at least *READ* access to the associated database." operationId: getData_1 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: page in: query required: false @@ -147,32 +145,26 @@ paths: type: string format: date-time responses: - "503": - description: Failed to establish connection with the metadata service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "404": description: Failed to find view in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "409": - description: View schema could not be mapped + "403": + description: Not allowed to retrieve view data content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Request pagination is malformed + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Not allowed to retrieve view data + "400": + description: Request pagination is malformed content: application/json: schema: @@ -192,6 +184,12 @@ paths: application/json: schema: type: string + "409": + description: View schema could not be mapped + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - basicAuth: [] - bearerAuth: [] @@ -210,14 +208,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -237,20 +235,20 @@ paths: type: integer format: int64 responses: - "400": - description: Request pagination or table data select query is malformed + "404": + description: Failed to find table in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to establish connection with the metadata service + "400": + description: Request pagination or table data select query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find table in metadata database + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: @@ -292,14 +290,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Authorization in: header required: true @@ -312,20 +310,20 @@ paths: $ref: "#/components/schemas/TupleUpdateDto" required: true responses: - "400": - description: Request pagination or table data select query is malformed + "404": + description: Failed to find table in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to establish connection with the metadata service + "400": + description: Request pagination or table data select query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find table in metadata database + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: @@ -354,14 +352,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Authorization in: header required: true @@ -374,21 +372,12 @@ paths: $ref: "#/components/schemas/TupleDto" required: true responses: - "404": - description: Failed to find table in metadata database or blob in storage - service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "400": description: Request pagination or table data select query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "201": - description: Created table data "503": description: Failed to establish connection with the metadata service or storage service @@ -402,6 +391,15 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "201": + description: Created table data + "404": + description: Failed to find table in metadata database or blob in storage + service + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - basicAuth: [] - bearerAuth: [] @@ -418,14 +416,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Authorization in: header required: true @@ -438,20 +436,20 @@ paths: $ref: "#/components/schemas/TupleDeleteDto" required: true responses: - "400": - description: Request pagination or table data select query is malformed + "404": + description: Failed to find table in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to establish connection with the metadata service + "400": + description: Request pagination or table data select query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find table in metadata database + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: @@ -481,14 +479,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -508,20 +506,20 @@ paths: type: integer format: int64 responses: - "400": - description: Request pagination or table data select query is malformed + "404": + description: Failed to find table in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to establish connection with the metadata service + "400": + description: Request pagination or table data select query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find table in metadata database + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: @@ -565,14 +563,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: subsetId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -592,8 +590,21 @@ paths: type: integer format: int64 responses: - "503": - description: Failed to communicate with database + "404": + description: Failed to find database in metadata database or query in query + store of the data database + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "403": + description: Not allowed to retrieve subset data + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "400": + description: Invalid pagination content: application/json: schema: @@ -619,21 +630,8 @@ paths: application/json: schema: type: string - "400": - description: Invalid pagination - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database in metadata database or query in query - store of the data database - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Not allowed to retrieve subset data + "503": + description: Failed to communicate with database content: application/json: schema: @@ -655,14 +653,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: subsetId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -682,8 +680,21 @@ paths: type: integer format: int64 responses: - "503": - description: Failed to communicate with database + "404": + description: Failed to find database in metadata database or query in query + store of the data database + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "403": + description: Not allowed to retrieve subset data + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "400": + description: Invalid pagination content: application/json: schema: @@ -709,21 +720,8 @@ paths: application/json: schema: type: string - "400": - description: Invalid pagination - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database in metadata database or query in query - store of the data database - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Not allowed to retrieve subset data + "503": + description: Failed to communicate with database content: application/json: schema: @@ -743,14 +741,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: queryId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -758,8 +756,8 @@ paths: $ref: "#/components/schemas/QueryPersistDto" required: true responses: - "503": - description: Failed to communicate with database + "403": + description: Not allowed to persist subset content: application/json: schema: @@ -770,27 +768,27 @@ paths: application/json: schema: $ref: "#/components/schemas/QueryDto" - "403": - description: Not allowed to persist subset + "404": + description: Failed to find database in metadata database or query in query + store of the data database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "417": - description: Failed to persist subset + "400": + description: Malformed select query content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database in metadata database or query in query - store of the data database + "417": + description: Failed to persist subset content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Malformed select query + "503": + description: Failed to communicate with database content: application/json: schema: @@ -813,14 +811,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Authorization in: header required: true @@ -835,20 +833,14 @@ paths: responses: "202": description: Imported dataset successfully - "503": - description: Failed to establish connection with the metadata service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "404": description: Failed to find table in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Import table dataset not allowed + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: @@ -859,6 +851,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "403": + description: Import table dataset not allowed + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - basicAuth: [] - bearerAuth: [] @@ -878,20 +876,22 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: persisted in: query required: false schema: type: boolean responses: - "503": - description: Failed to communicate with database + "200": + description: Found subsets content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" + type: array + items: + $ref: "#/components/schemas/QueryDto" "404": description: Failed to find database in metadata database or query in query store of the data database @@ -899,16 +899,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "200": - description: Found subsets + "403": + description: Not allowed to find subsets content: application/json: schema: - type: array - items: - $ref: "#/components/schemas/QueryDto" - "403": - description: Not allowed to find subsets + $ref: "#/components/schemas/ApiErrorDto" + "503": + description: Failed to communicate with database content: application/json: schema: @@ -930,8 +928,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -954,7 +952,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/ExecuteStatementDto" + $ref: "#/components/schemas/SubsetDto" required: true responses: "201": @@ -963,12 +961,6 @@ paths: application/json: schema: type: string - "503": - description: Failed to communicate with database - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "501": description: Failed to execute query as it contains non-supported keywords content: @@ -988,14 +980,20 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "417": + description: Failed to insert query into query store of data database + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "400": description: Malformed select query content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "417": - description: Failed to insert query into query store of data database + "503": + description: Failed to communicate with database content: application/json: schema: @@ -1017,14 +1015,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -1032,20 +1030,26 @@ paths: type: string format: date-time responses: - "503": - description: Failed to establish connection with the metadata service + "400": + description: Request pagination or view data select query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Export view data not allowed + "404": + description: Failed to find view in metadata database or export dataset content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find view in metadata database or export dataset + "503": + description: Failed to establish connection with the metadata service + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "403": + description: Export view data not allowed content: application/json: schema: @@ -1057,12 +1061,6 @@ paths: schema: type: string format: binary - "400": - description: Request pagination or view data select query is malformed - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" security: - basicAuth: [] - bearerAuth: [] @@ -1080,14 +1078,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: size in: query required: false @@ -1095,6 +1093,14 @@ paths: type: integer format: int64 responses: + "200": + description: Found table history + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/TableHistoryDto" "403": description: Find table history not allowed content: @@ -1107,26 +1113,18 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find table history in data database - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "400": description: "Invalid pagination size request, must be > 0" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "200": - description: Found table history + "404": + description: Failed to find table history in data database content: application/json: schema: - type: array - items: - $ref: "#/components/schemas/TableHistoryDto" + $ref: "#/components/schemas/ApiErrorDto" security: - basicAuth: [] - bearerAuth: [] @@ -1144,14 +1142,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -1159,14 +1157,14 @@ paths: type: string format: date-time responses: - "400": - description: Request pagination or table data select query is malformed + "404": + description: Failed to find table in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to establish connection with the metadata service + "400": + description: Request pagination or table data select query is malformed content: application/json: schema: @@ -1178,8 +1176,8 @@ paths: schema: type: string format: binary - "404": - description: Failed to find table in metadata database + "503": + description: Failed to establish connection with the metadata service content: application/json: schema: @@ -1209,14 +1207,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: subsetId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Accept in: header required: true @@ -1229,31 +1227,25 @@ paths: type: string format: date-time responses: - "503": - description: Failed to communicate with database - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Not allowed to find subset + "200": + description: Found subset content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" + $ref: "#/components/schemas/QueryDto" + text/csv: {} "406": description: Failed to find acceptable representation content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "200": - description: Found subset + "403": + description: Not allowed to find subset content: application/json: schema: - $ref: "#/components/schemas/QueryDto" - text/csv: {} + $ref: "#/components/schemas/ApiErrorDto" "404": description: Failed to find database in metadata database or query in query store of the data database @@ -1267,6 +1259,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "503": + description: Failed to communicate with database + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - basicAuth: [] - bearerAuth: [] @@ -1395,9 +1393,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 11 + type: string + format: uuid + example: e41f94a6-2b94-4a12-ac0e-678684e1c070 affiliation: type: string example: Brown University @@ -1435,6 +1433,7 @@ components: required: - creators - database_id + - descriptions - id - owned_by - publication_year @@ -1445,9 +1444,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: b97cd56b-66ca-4354-9e6c-f47210cfaaec type: type: string example: database @@ -1464,6 +1463,10 @@ components: type: array items: $ref: "#/components/schemas/IdentifierTitleDto" + descriptions: + type: array + items: + $ref: "#/components/schemas/IdentifierDescriptionDto" doi: type: string example: 10.1038/nphys1170 @@ -1477,21 +1480,18 @@ components: - draft - published database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: fc29f89c-86a8-4020-9e36-4d954736c6cc query_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid table_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid view_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid publication_year: type: integer format: int32 @@ -1500,15 +1500,225 @@ components: type: string format: uuid example: 2f45ef7a-7f9b-4667-9156-152c87fe1ca5 + IdentifierDescriptionDto: + required: + - id + type: object + properties: + id: + type: string + format: uuid + example: e0e9692c-910b-4b60-b53a-fc7c358a917d + description: + type: string + example: "Air quality reports at Stephansplatz, Vienna" + language: + type: string + example: en + enum: + - ab + - aa + - af + - ak + - sq + - am + - ar + - an + - hy + - as + - av + - ae + - ay + - az + - bm + - ba + - eu + - be + - bn + - bh + - bi + - bs + - br + - bg + - my + - ca + - km + - ch + - ce + - ny + - zh + - cu + - cv + - kw + - co + - cr + - hr + - cs + - da + - dv + - nl + - dz + - en + - eo + - et + - ee + - fo + - fj + - fi + - fr + - ff + - gd + - gl + - lg + - ka + - de + - ki + - el + - kl + - gn + - gu + - ht + - ha + - he + - hz + - hi + - ho + - hu + - is + - io + - ig + - id + - ia + - ie + - iu + - ik + - ga + - it + - ja + - jv + - kn + - kr + - ks + - kk + - rw + - kv + - kg + - ko + - kj + - ku + - ky + - lo + - la + - lv + - lb + - li + - ln + - lt + - lu + - mk + - mg + - ms + - ml + - mt + - gv + - mi + - mr + - mh + - ro + - mn + - na + - nv + - nd + - ng + - ne + - se + - "no" + - nb + - nn + - ii + - oc + - oj + - or + - om + - os + - pi + - pa + - ps + - fa + - pl + - pt + - qu + - rm + - rn + - ru + - sm + - sg + - sa + - sc + - sr + - sn + - sd + - si + - sk + - sl + - so + - st + - nr + - es + - su + - sw + - ss + - sv + - tl + - ty + - tg + - ta + - tt + - te + - th + - bo + - ti + - to + - ts + - tn + - tr + - tk + - tw + - ug + - uk + - ur + - uz + - ve + - vi + - vo + - wa + - cy + - fy + - wo + - xh + - yi + - yo + - za + - zu + type: + type: string + example: Abstract + enum: + - Abstract + - Methods + - SeriesInformation + - TableOfContents + - TechnicalInfo + - Other IdentifierTitleDto: required: - id type: object properties: id: - type: integer - format: int64 - example: 4 + type: string + format: uuid + example: 70ce5164-fd74-413f-8712-f996b91defbf title: type: string example: Airquality Demonstrator @@ -1721,9 +1931,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 4 + type: string + format: uuid + example: 83ea2326-f8f6-4263-baf8-cdf88a54efc7 owner: $ref: "#/components/schemas/UserBriefDto" execution: @@ -1744,9 +1954,9 @@ components: items: $ref: "#/components/schemas/IdentifierBriefDto" database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: fc29f89c-86a8-4020-9e36-4d954736c6cc query_normalized: type: string example: SELECT `id` FROM `air_quality` @@ -1829,14 +2039,72 @@ components: line_termination: type: string example: \r\n - ExecuteStatementDto: + FilterDto: + required: + - column_id + - operator_id + - type + - value + type: object + properties: + type: + type: string + example: where + enum: + - where + - or + - and + value: + type: string + example: "1" + column_id: + type: string + format: uuid + example: 14128033-54b5-4818-a489-21b0dded86e2 + operator_id: + type: string + format: uuid + example: 67c5b54d-2eb0-4f42-8dc1-a504562e9f32 + OrderDto: required: - - statement + - column_id type: object properties: - statement: + direction: type: string - example: SELECT `id` FROM `air_quality` + example: asc + enum: + - asc + - desc + column_id: + type: string + format: uuid + example: e891ba86-0258-41a6-a8d9-ff58bc10b618 + SubsetDto: + required: + - columns + - table_id + type: object + properties: + columns: + type: array + example: + - e891ba86-0258-41a6-a8d9-ff58bc10b618 + items: + type: string + format: uuid + filter: + type: array + items: + $ref: "#/components/schemas/FilterDto" + order: + type: array + items: + $ref: "#/components/schemas/OrderDto" + table_id: + type: string + format: uuid + example: f7df2a7d-4ade-4c78-97b0-7c744d0893c7 TableHistoryDto: required: - event @@ -1850,6 +2118,10 @@ components: example: 2021-03-12T15:26:21Z event: type: string + example: INSERT + enum: + - insert + - delete total: type: integer format: int64 diff --git a/.docs/.openapi/api-metadata.yaml b/.docs/.openapi/api-metadata.yaml index 18fb71db29..7331cf78f7 100644 --- a/.docs/.openapi/api-metadata.yaml +++ b/.docs/.openapi/api-metadata.yaml @@ -8,16 +8,146 @@ info: license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0 - version: 1.6.2 + version: 1.7.0 externalDocs: description: Sourcecode Documentation - url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6.2/system-services-metadata/ + url: https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.7.0/system-services-metadata/ servers: - url: http://localhost description: Development instance - url: https://test.dbrepo.tuwien.ac.at description: Staging instance paths: + /api/user/{userId}: + get: + tags: + - user-endpoint + summary: Get user + description: Gets own user information from the metadata database. Requires + authentication. Foreign user information can only be obtained if additional + role `find-foreign-user` is present. Finding information about internal users + results in a 404 error. + operationId: find + parameters: + - name: userId + in: path + required: true + schema: + type: string + format: uuid + responses: + "403": + description: Find user is not permitted + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "200": + description: Found user + content: + application/json: + schema: + $ref: "#/components/schemas/UserDto" + "404": + description: User was not found + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + security: + - bearerAuth: [] + - basicAuth: [] + put: + tags: + - user-endpoint + summary: Update user + description: Updates user with id. Requires role `modify-user-information`. + operationId: modify + parameters: + - name: userId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/UserUpdateDto" + required: true + responses: + "400": + description: Modify user query is malformed + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "403": + description: Not allowed to modify user metadata + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "404": + description: Failed to find database/user in metadata database + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "503": + description: Failed to modify user at auth service + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "202": + description: Modified user information + content: + application/json: + schema: + $ref: "#/components/schemas/UserDto" + security: + - bearerAuth: [] + - basicAuth: [] + head: + tags: + - user-endpoint + summary: Get user + description: Gets own user information from the metadata database. Requires + authentication. Foreign user information can only be obtained if additional + role `find-foreign-user` is present. Finding information about internal users + results in a 404 error. + operationId: find_1 + parameters: + - name: userId + in: path + required: true + schema: + type: string + format: uuid + responses: + "403": + description: Find user is not permitted + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "200": + description: Found user + content: + application/json: + schema: + $ref: "#/components/schemas/UserDto" + "404": + description: User was not found + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + security: + - bearerAuth: [] + - basicAuth: [] /api/database: get: tags: @@ -56,7 +186,7 @@ paths: - database-endpoint summary: Create database description: Creates a database in the container with id. Requires roles `create-database`. - operationId: create_5 + operationId: create_4 requestBody: content: application/json: @@ -64,9 +194,8 @@ paths: $ref: "#/components/schemas/CreateDatabaseDto" required: true responses: - "403": - description: Database create permission is missing or grant permissions - at broker service failed + "400": + description: Database create query is malformed or image is not supported content: application/json: schema: @@ -77,26 +206,21 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Database create query is malformed or image is not supported - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "403": + description: Database create permission is missing or grant permissions + at broker service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to fin container/user/database in metadata database + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "409": + description: Query store could not be created content: application/json: schema: @@ -107,8 +231,14 @@ paths: application/json: schema: $ref: "#/components/schemas/DatabaseBriefDto" - "409": - description: Query store could not be created + "404": + description: Failed to fin container/user/database in metadata database + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "503": + description: Failed to save in search service content: application/json: schema: @@ -158,14 +288,14 @@ paths: \ with HTTP method **HEAD** only the status. When the user has at least *READ*\ \ access, the status 200 is returned, 403 otherwise. Requires role `check-database-access`\ \ or `check-foreign-database-access`." - operationId: find + operationId: find_2 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: userId in: path required: true @@ -173,12 +303,6 @@ paths: type: string format: uuid responses: - "200": - description: Found database access - content: - application/json: - schema: - $ref: "#/components/schemas/DatabaseAccessDto" "403": description: No access to this database content: @@ -191,6 +315,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "200": + description: Found database access + content: + application/json: + schema: + $ref: "#/components/schemas/DatabaseAccessDto" security: - bearerAuth: [] - basicAuth: [] @@ -206,8 +336,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: userId in: path required: true @@ -221,36 +351,36 @@ paths: $ref: "#/components/schemas/CreateAccessDto" required: true responses: - "403": - description: Modify access not permitted when no access is granted in the - first place + "404": + description: Database or user not found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Access could not be updated due to connection error in the - data service + "403": + description: Modify access not permitted when no access is granted in the + first place content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Access could not be updated in the data service + "400": + description: Modify access query or database connection is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" "202": description: Modified access - "404": - description: Database or user not found + "503": + description: Access could not be updated in the data service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Modify access query or database connection is malformed + "502": + description: Access could not be updated due to connection error in the + data service content: application/json: schema: @@ -264,14 +394,14 @@ paths: summary: Give access description: Give a user with given id access to some database with given id. Requires role `create-database-access`. - operationId: create_8 + operationId: create_7 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: userId in: path required: true @@ -285,8 +415,8 @@ paths: $ref: "#/components/schemas/CreateAccessDto" required: true responses: - "502": - description: Access could not be created due to connection error + "404": + description: Database or user not found content: application/json: schema: @@ -297,30 +427,30 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Granting access query or database connection is malformed + "502": + description: Access could not be created due to connection error content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Failed giving access + "202": + description: Granting access succeeded content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Database or user not found + $ref: "#/components/schemas/DatabaseAccessDto" + "400": + description: Granting access query or database connection is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Granting access succeeded + "403": + description: Failed giving access content: application/json: schema: - $ref: "#/components/schemas/DatabaseAccessDto" + $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -336,8 +466,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: userId in: path required: true @@ -345,20 +475,24 @@ paths: type: string format: uuid responses: + "403": + description: Revoke of access not permitted as no access was found + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "502": description: Access could not be created due to connection error content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Revoke of access not permitted as no access was found + "503": + description: Access could not be revoked in the data service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Deleted access "400": description: Modify access query or database connection is malformed content: @@ -371,12 +505,8 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Access could not be revoked in the data service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" + "202": + description: Deleted access security: - bearerAuth: [] - basicAuth: [] @@ -389,14 +519,14 @@ paths: \ with HTTP method **HEAD** only the status. When the user has at least *READ*\ \ access, the status 200 is returned, 403 otherwise. Requires role `check-database-access`\ \ or `check-foreign-database-access`." - operationId: find_1 + operationId: find_3 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: userId in: path required: true @@ -404,12 +534,6 @@ paths: type: string format: uuid responses: - "200": - description: Found database access - content: - application/json: - schema: - $ref: "#/components/schemas/DatabaseAccessDto" "403": description: No access to this database content: @@ -422,259 +546,29 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - security: - - bearerAuth: [] - - basicAuth: [] - /api/user/{userId}: - get: - tags: - - user-endpoint - summary: Get user - description: Gets own user information from the metadata database. Requires - authentication. Foreign user information can only be obtained if additional - role `find-foreign-user` is present. Finding information about internal users - results in a 404 error. - operationId: find_2 - parameters: - - name: userId - in: path - required: true - schema: - type: string - format: uuid - responses: - "404": - description: User was not found - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "200": - description: Found user - content: - application/json: - schema: - $ref: "#/components/schemas/UserDto" - "403": - description: Find user is not permitted - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - security: - - bearerAuth: [] - - basicAuth: [] - put: - tags: - - user-endpoint - summary: Update user - description: Updates user with id. Requires role `modify-user-information`. - operationId: modify - parameters: - - name: userId - in: path - required: true - schema: - type: string - format: uuid - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/UserUpdateDto" - required: true - responses: - "202": - description: Modified user information - content: - application/json: - schema: - $ref: "#/components/schemas/UserDto" - "403": - description: Not allowed to modify user metadata - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Modify user query is malformed - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database/user in metadata database - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - security: - - bearerAuth: [] - - basicAuth: [] - /api/user/{userId}/password: - put: - tags: - - user-endpoint - summary: Update user password - description: Updates password of user with id. Requires authentication. - operationId: password - parameters: - - name: userId - in: path - required: true - schema: - type: string - format: uuid - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/UserPasswordDto" - required: true - responses: - "400": - description: Invalid password payload - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Modified user password - "403": - description: Not allowed to change foreign user password - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database/user in metadata database - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to get user in auth service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to auth service failed + description: Found database access content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" + $ref: "#/components/schemas/DatabaseAccessDto" security: - bearerAuth: [] - basicAuth: [] - /api/user/token: - put: - tags: - - user-endpoint - summary: Refresh token - description: Refreshes user token by refresh token. - operationId: refreshToken - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/RefreshTokenRequestDto" - required: true - responses: - "403": - description: Not allowed - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Invalid refresh token - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Refreshed user token - content: - application/json: - schema: - $ref: "#/components/schemas/TokenDto" - "502": - description: Connection to auth service failed - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - post: - tags: - - user-endpoint - summary: Create token - description: Creates a user token via the Auth Service. - operationId: getToken - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/LoginRequestDto" - required: true - responses: - "404": - description: Failed to find user in auth database - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "428": - description: Account is not fully setup in auth service (requires password - change?) - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Invalid login request - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Obtained user token - content: - application/json: - schema: - $ref: "#/components/schemas/TokenDto" - "403": - description: Not allowed to get token - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to get user in auth service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to auth service failed - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" /api/ontology/{ontologyId}: get: tags: - ontology-endpoint summary: Find ontology description: Finds an ontology with id in the metadata database. - operationId: find_3 + operationId: find_4 parameters: - name: ontologyId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: "200": description: Find one ontology @@ -699,8 +593,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -734,19 +628,19 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: + "202": + description: Deleted ontology successfully + content: + application/json: {} "404": description: Could not find ontology content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Deleted ontology successfully - content: - application/json: {} security: - bearerAuth: [] - basicAuth: [] @@ -762,8 +656,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -797,8 +691,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: "404": description: Could not find message @@ -825,21 +719,21 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: - "200": - description: Found image - content: - application/json: - schema: - $ref: "#/components/schemas/ImageDto" "404": description: Image could not be found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "200": + description: Found image + content: + application/json: + schema: + $ref: "#/components/schemas/ImageDto" put: tags: - image-endpoint @@ -852,8 +746,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -888,17 +782,17 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: + "202": + description: Deleted image successfully "404": description: Image could not be found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Deleted image successfully security: - bearerAuth: [] - basicAuth: [] @@ -909,22 +803,22 @@ paths: summary: Find identifier description: Finds an identifier with id. The response format depends on the HTTP `Accept` header set on the request. - operationId: find_6 + operationId: find_7 parameters: - name: identifierId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Accept in: header required: true schema: type: string responses: - "410": - description: Failed to retrieve from S3 endpoint + "404": + description: Identifier could not be found content: application/json: schema: @@ -935,12 +829,30 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "410": + description: Failed to retrieve from S3 endpoint + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "503": description: Failed to find in data service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "403": + description: Not allowed to view identifier + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "406": + description: Failed to find acceptable representation + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "200": description: Found identifier successfully content: @@ -956,27 +868,15 @@ paths: text/bibliography; style=apa: {} text/bibliography; style=ieee: {} text/bibliography; style=bibtex: {} - "400": - description: "Identifier could not be exported, the requested style is not\ - \ known" - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "409": description: Exported resource was not found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Identifier could not be found - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "406": - description: Failed to find acceptable representation + "400": + description: "Identifier could not be exported, the requested style is not\ + \ known" content: application/json: schema: @@ -995,8 +895,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -1004,14 +904,20 @@ paths: $ref: "#/components/schemas/IdentifierSaveDto" required: true responses: + "202": + description: Saved identifier + content: + application/json: + schema: + $ref: "#/components/schemas/IdentifierDto" "400": description: Identifier form contains invalid request data content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: "Failed to find database, table or view" + "502": + description: Connection to search service failed content: application/json: schema: @@ -1022,24 +928,18 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "404": + description: "Failed to find database, table or view" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "503": + description: Failed to save in search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Saved identifier - content: - application/json: - schema: - $ref: "#/components/schemas/IdentifierDto" security: - bearerAuth: [] - basicAuth: [] @@ -1054,8 +954,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: "403": description: Deleting identifier not permitted @@ -1063,26 +963,26 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Identifier or database could not be found + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to delete in search service + "404": + description: Identifier or database could not be found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "202": + description: Deleted identifier + "503": + description: Failed to delete in search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Deleted identifier security: - bearerAuth: [] - basicAuth: [] @@ -1099,17 +999,23 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: + "202": + description: Published identifier + content: + application/json: + schema: + $ref: "#/components/schemas/IdentifierDto" "400": description: Identifier form contains invalid request data content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: "Failed to find database, table or view" + "502": + description: Connection to search service failed content: application/json: schema: @@ -1120,24 +1026,18 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "404": + description: "Failed to find database, table or view" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "503": + description: Failed to save in search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Published identifier - content: - application/json: - schema: - $ref: "#/components/schemas/IdentifierDto" security: - bearerAuth: [] - basicAuth: [] @@ -1154,8 +1054,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -1163,38 +1063,38 @@ paths: $ref: "#/components/schemas/DatabaseModifyVisibilityDto" required: true responses: - "400": - description: The visibility payload is malformed + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Visibility modified successfully + "404": + description: Failed to find database in metadata database content: application/json: schema: - $ref: "#/components/schemas/DatabaseBriefDto" - "503": - description: Failed to save in search service + $ref: "#/components/schemas/ApiErrorDto" + "403": + description: Visibility modification is not permitted content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "202": + description: Visibility modified successfully content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database in metadata database + $ref: "#/components/schemas/DatabaseBriefDto" + "400": + description: The visibility payload is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Visibility modification is not permitted + "503": + description: Failed to save in search service content: application/json: schema: @@ -1208,60 +1108,35 @@ paths: - view-endpoint summary: Get view description: Gets a view with id in the metadata database. - operationId: find_7 + operationId: find_8 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: - "403": - description: Find view is not permitted + "404": + description: "Database, view or user could not be found" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: "Database, view or user could not be found" + "403": + description: Find view is not permitted content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" "200": description: Find view successfully - headers: - X-Username: - description: The authentication username - style: simple - Access-Control-Expose-Headers: - description: Expose custom headers - style: simple - X-Type: - description: The JDBC connection type - style: simple - X-View: - description: The view internal name - style: simple - X-Database: - description: The database internal name - style: simple - X-Password: - description: The authentication password - style: simple - X-Host: - description: The database hostname - style: simple - X-Port: - description: The database port number - style: simple content: application/json: schema: @@ -1281,14 +1156,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -1296,20 +1171,20 @@ paths: $ref: "#/components/schemas/ViewUpdateDto" required: true responses: - "403": - description: Update not allowed + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "404": + description: Database or View could not be found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Database or View could not be found + "400": + description: Update view query is malformed content: application/json: schema: @@ -1320,14 +1195,14 @@ paths: '*/*': schema: $ref: "#/components/schemas/ViewBriefDto" - "502": - description: Connection to search service failed + "403": + description: Update not allowed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Update view query is malformed + "503": + description: Failed to save in search service content: application/json: schema: @@ -1346,31 +1221,31 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: - "202": - description: Delete view successfully - "423": - description: Delete view resulted in an invalid query statement - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "404": description: "Database, view or user could not be found" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Delete view query is malformed + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "202": + description: Delete view successfully + "403": + description: Deletion not allowed content: application/json: schema: @@ -1381,14 +1256,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "400": + description: Delete view query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Deletion not allowed + "423": + description: Delete view resulted in an invalid query statement content: application/json: schema: @@ -1411,17 +1286,17 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: - "502": - description: Failed to establish connection with broker service + "403": + description: Access to the database is forbidden content: application/json: schema: @@ -1432,34 +1307,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to obtain queue information from broker service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "200": description: Find table successfully - headers: - X-Username: - description: The authentication username - style: simple - Access-Control-Expose-Headers: - description: Expose custom headers - style: simple - X-Password: - description: The authentication password - style: simple content: application/json: schema: $ref: "#/components/schemas/TableDto" - "403": - description: Access to the database is forbidden - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -1474,14 +1327,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -1489,38 +1342,38 @@ paths: $ref: "#/components/schemas/TableUpdateDto" required: true responses: - "400": - description: Update table visibility payload is malformed + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "404": + description: Table could not be found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "403": + description: Update table visibility not permitted content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Updated the table + "400": + description: Update table visibility payload is malformed content: application/json: schema: - $ref: "#/components/schemas/TableBriefDto" - "403": - description: Update table visibility not permitted + $ref: "#/components/schemas/ApiErrorDto" + "202": + description: Updated the table content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Table could not be found + $ref: "#/components/schemas/TableBriefDto" + "503": + description: Failed to save in search service content: application/json: schema: @@ -1541,43 +1394,43 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: - "400": - description: Delete table query resulted in an invalid query statement + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Delete table successfully - "404": - description: "Table, database or container could not be found" + "400": + description: Delete table query resulted in an invalid query statement content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "403": + description: Access to the database is forbidden content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "404": + description: "Table, database or container could not be found" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Access to the database is forbidden + "202": + description: Delete table successfully + "503": + description: Failed to save in search service content: application/json: schema: @@ -1599,29 +1452,23 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: - "400": - description: Failed to map column statistic to known columns - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Not the owner + "400": + description: Failed to map column statistic to known columns content: application/json: schema: @@ -1632,14 +1479,20 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "403": + description: Not the owner content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" "202": description: Updated table statistics successfully + "503": + description: Failed to save in search service + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -1658,20 +1511,20 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: columnId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -1679,39 +1532,39 @@ paths: $ref: "#/components/schemas/ColumnSemanticsUpdateDto" required: true responses: - "503": - description: Failed to save in search service + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Updated column semantics successfully + "403": + description: Access to the database is forbidden content: application/json: schema: - $ref: "#/components/schemas/ColumnDto" - "404": - description: Failed to find user/table/database/ontology in metadata database + $ref: "#/components/schemas/ApiErrorDto" + "400": + description: Update semantic concept query is malformed or update unit of + measurement query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "404": + description: Failed to find user/table/database/ontology in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Update semantic concept query is malformed or update unit of - measurement query is malformed + "202": + description: Updated column semantics successfully content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Access to the database is forbidden + $ref: "#/components/schemas/ColumnDto" + "503": + description: Failed to save in search service content: application/json: schema: @@ -1732,8 +1585,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -1741,38 +1594,38 @@ paths: $ref: "#/components/schemas/DatabaseTransferDto" required: true responses: - "400": - description: Owner payload is malformed + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Transfer of ownership was successful + "400": + description: Owner payload is malformed content: application/json: schema: - $ref: "#/components/schemas/DatabaseBriefDto" - "503": - description: Failed to save in search service + $ref: "#/components/schemas/ApiErrorDto" + "403": + description: Transfer of ownership is not permitted content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "404": + description: Database or user could not be found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Transfer of ownership is not permitted + "202": + description: Transfer of ownership was successful content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Database or user could not be found + $ref: "#/components/schemas/DatabaseBriefDto" + "503": + description: Failed to save in search service content: application/json: schema: @@ -1794,9 +1647,15 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "200": description: Refreshed database views metadata content: @@ -1809,20 +1668,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "404": + description: Failed to find database in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database in metadata database + "503": + description: Failed to save in search service content: application/json: schema: @@ -1844,27 +1697,21 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: + "502": + description: Connection to search service failed + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "400": description: Failed to parse payload at search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "200": description: Refreshed database tables metadata content: @@ -1878,7 +1725,13 @@ paths: schema: $ref: "#/components/schemas/ApiErrorDto" "404": - description: Failed to fin user/database in metadata database + description: Failed to find database in metadata database + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "503": + description: Failed to save in search service content: application/json: schema: @@ -1898,9 +1751,15 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: + "404": + description: Database or user could not be found + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "200": description: View of image was successful content: @@ -1910,12 +1769,6 @@ paths: items: type: string format: byte - "404": - description: Database or user could not be found - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -1931,8 +1784,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -1940,129 +1793,45 @@ paths: $ref: "#/components/schemas/DatabaseModifyImageDto" required: true responses: - "403": - description: Modify of image is not permitted - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Database could not be found - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "502": description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Modify of image was successful + "403": + description: Modify of image is not permitted content: application/json: schema: - $ref: "#/components/schemas/DatabaseBriefDto" + $ref: "#/components/schemas/ApiErrorDto" "410": description: File was not found in the Storage Service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - security: - - bearerAuth: [] - - basicAuth: [] - /api/user: - get: - tags: - - user-endpoint - summary: List users - description: "Lists users known to the metadata database. Internal users are\ - \ omitted from the result list. If the optional query parameter `username`\ - \ is present, the result list can be filtered by matching this exact username." - operationId: findAll - parameters: - - name: username - in: query - required: false - schema: - type: string - responses: - "200": - description: List users - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/UserBriefDto" - post: - tags: - - user-endpoint - summary: Create user - description: Creates a user in the auth service and metadata database. Requires - that no credentials are sent in the request. - operationId: create - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/CreateUserDto" - required: true - responses: - "201": - description: Created user + "202": + description: Modify of image was successful content: application/json: schema: - $ref: "#/components/schemas/UserDto" + $ref: "#/components/schemas/DatabaseBriefDto" "404": - description: Default role not found - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Failed to create in auth service - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Internal authentication to the auth service is invalid - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "409": - description: User with username already exists - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Parameters are not well-formed (likely email) - content: - application/json: {} - "417": - description: User with e-mail already exists + description: Database could not be found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" "503": - description: Failed to create in auth service + description: Failed to save in search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + security: + - bearerAuth: [] + - basicAuth: [] /api/ontology: get: tags: @@ -2084,7 +1853,7 @@ paths: - ontology-endpoint summary: Create ontology description: Creates an ontology in the metadata database. Requires role `create-ontology`. - operationId: create_1 + operationId: create requestBody: content: application/json: @@ -2132,7 +1901,7 @@ paths: - message-endpoint summary: Create message description: Creates a message in the metadata database. Requires role `create-maintenance-message`. - operationId: create_2 + operationId: create_1 requestBody: content: application/json: @@ -2171,7 +1940,7 @@ paths: summary: Create image description: Creates a container image in the metadata database. Requires role `create-image`. - operationId: create_3 + operationId: create_2 requestBody: content: application/json: @@ -2179,18 +1948,18 @@ paths: $ref: "#/components/schemas/ImageCreateDto" required: true responses: - "201": - description: Created image - content: - application/json: - schema: - $ref: "#/components/schemas/ImageDto" "409": description: Image already exists content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "201": + description: Created image + content: + application/json: + schema: + $ref: "#/components/schemas/ImageDto" "400": description: Image specification is invalid content: @@ -2208,30 +1977,48 @@ paths: description: Lists all identifiers known to the metadata database operationId: findAll_4 parameters: + - name: type + in: query + required: false + schema: + type: string + enum: + - database + - subset + - table + - view + - name: status + in: query + required: false + schema: + type: string + enum: + - draft + - published - name: dbid in: query required: false schema: - type: integer - format: int64 + type: string + format: uuid - name: qid in: query required: false schema: - type: integer - format: int64 + type: string + format: uuid - name: vid in: query required: false schema: - type: integer - format: int64 + type: string + format: uuid - name: tid in: query required: false schema: - type: integer - format: int64 + type: string + format: uuid - name: Accept in: header required: true @@ -2251,13 +2038,6 @@ paths: type: array items: $ref: "#/components/schemas/LdDatasetDto" - "406": - description: "Identifier could not be exported, the requested style is not\ - \ known" - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" post: tags: - identifier-endpoint @@ -2266,7 +2046,7 @@ paths: can only be created for objects the user has at least *READ* access in the associated database (requires role `create-identifier`) or for any object in any database (requires role `create-foreign-identifier`). - operationId: create_4 + operationId: create_3 requestBody: content: application/json: @@ -2274,20 +2054,14 @@ paths: $ref: "#/components/schemas/CreateIdentifierDto" required: true responses: - "201": - description: Drafted identifier - content: - application/json: - schema: - $ref: "#/components/schemas/IdentifierDto" "400": description: Identifier form contains invalid request data content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: "Failed to find database, table or view" + "502": + description: Connection to search service failed content: application/json: schema: @@ -2298,14 +2072,20 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "201": + description: Drafted identifier + content: + application/json: + schema: + $ref: "#/components/schemas/IdentifierDto" + "404": + description: "Failed to find database, table or view" content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "503": + description: Failed to save in search service content: application/json: schema: @@ -2325,9 +2105,15 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: + "404": + description: Database or user could not be found + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" "200": description: Find views successfully content: @@ -2336,12 +2122,6 @@ paths: type: array items: $ref: "#/components/schemas/ViewBriefDto" - "404": - description: Database or user could not be found - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -2351,14 +2131,14 @@ paths: summary: Create view description: Creates a view. This can only be performed by the database owner. Requires role `create-database-view`. - operationId: create_6 + operationId: create_5 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -2366,32 +2146,26 @@ paths: $ref: "#/components/schemas/CreateViewDto" required: true responses: - "201": - description: Create view successfully - content: - application/json: - schema: - $ref: "#/components/schemas/ViewBriefDto" - "423": - description: Create view resulted in an invalid query statement + "400": + description: Create view query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "502": + description: Connection to search service failed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "201": + description: Create view successfully content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Create view query is malformed + $ref: "#/components/schemas/ViewBriefDto" + "404": + description: Failed to find database/user in metadata database. content: application/json: schema: @@ -2402,8 +2176,20 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database/user in metadata database. + "423": + description: Create view resulted in an invalid query statement + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "503": + description: Failed to save in search service + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "409": + description: View exists with name content: application/json: schema: @@ -2425,8 +2211,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: "403": description: List tables not permitted @@ -2434,12 +2220,6 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Database could not be found - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "200": description: List tables content: @@ -2448,6 +2228,12 @@ paths: type: array items: $ref: "#/components/schemas/TableBriefDto" + "404": + description: Database could not be found + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -2456,14 +2242,14 @@ paths: - table-endpoint summary: Create table description: Creates a table in the database with id. Requires role `create-table`. - operationId: create_7 + operationId: create_6 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -2471,26 +2257,20 @@ paths: $ref: "#/components/schemas/CreateTableDto" required: true responses: - "409": - description: Create table conflicts with existing table name - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "400": description: Create table query is malformed content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: "Database, container or user could not be found" + "409": + description: Create table conflicts with existing table name content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "503": - description: Failed to save in search service + "502": + description: Connection to search service failed content: application/json: schema: @@ -2501,18 +2281,24 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to search service failed + "201": + description: Created a new table + content: + application/json: + schema: + $ref: "#/components/schemas/TableBriefDto" + "503": + description: Failed to save in search service content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "201": - description: Created a new table + "404": + description: "Database, container or user could not be found" content: application/json: schema: - $ref: "#/components/schemas/TableBriefDto" + $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -2544,7 +2330,7 @@ paths: - container-endpoint summary: Create container description: Creates a container in the metadata database. Requires role `create-container`. - operationId: create_9 + operationId: create_8 requestBody: content: application/json: @@ -2552,12 +2338,6 @@ paths: $ref: "#/components/schemas/CreateContainerDto" required: true responses: - "409": - description: Container name already exists - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "403": description: "Create container not permitted, need authority `create-container`" content: @@ -2570,8 +2350,8 @@ paths: application/json: schema: $ref: "#/components/schemas/ContainerDto" - "400": - description: Container payload malformed + "409": + description: Container name already exists content: application/json: schema: @@ -2582,9 +2362,39 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "400": + description: Container payload malformed + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] + /api/user: + get: + tags: + - user-endpoint + summary: List users + description: "Lists users known to the metadata database. Internal users are\ + \ omitted from the result list. If the optional query parameter `username`\ + \ is present, the result list can be filtered by matching this exact username." + operationId: findAll + parameters: + - name: username + in: query + required: false + schema: + type: string + responses: + "200": + description: List users + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/UserBriefDto" /api/unit: get: tags: @@ -2608,14 +2418,14 @@ paths: summary: Find entities description: Finds semantic entities by label or uri in an ontology with id. Requires role `execute-semantic-query`. - operationId: find_4 + operationId: find_5 parameters: - name: ontologyId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: label in: query required: false @@ -2627,20 +2437,22 @@ paths: schema: type: string responses: - "422": - description: Ontology does not have rdf or sparql endpoint + "200": + description: Found entities content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" + type: array + items: + $ref: "#/components/schemas/EntityDto" "400": description: Filter params are invalid content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Could not find ontology + "422": + description: Ontology does not have rdf or sparql endpoint content: application/json: schema: @@ -2651,14 +2463,12 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "200": - description: Found entities + "404": + description: Could not find ontology content: application/json: schema: - type: array - items: - $ref: "#/components/schemas/EntityDto" + $ref: "#/components/schemas/ApiErrorDto" security: - bearerAuth: [] - basicAuth: [] @@ -2687,27 +2497,27 @@ paths: - message-endpoint summary: Find message description: Finds a message with id in the metadata database. - operationId: find_5 + operationId: find_6 parameters: - name: messageId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: - "200": - description: Get messages - content: - application/json: - schema: - $ref: "#/components/schemas/BannerMessageDto" "404": description: Could not find message content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "200": + description: Get messages + content: + application/json: + schema: + $ref: "#/components/schemas/BannerMessageDto" /api/license: get: tags: @@ -2739,18 +2549,18 @@ paths: schema: type: string responses: - "404": - description: Failed to find metadata for identifier - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "200": description: Retrieved metadata from identifier content: application/json: schema: $ref: "#/components/schemas/IdentifierDto" + "404": + description: Failed to find metadata for identifier + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" /api/database/{databaseId}: get: tags: @@ -2763,21 +2573,9 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: - "404": - description: "Database, user or exchange could not be found" - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "403": - description: Not allowed to view database - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" "200": description: Database found successfully headers: @@ -2794,14 +2592,14 @@ paths: application/json: schema: $ref: "#/components/schemas/DatabaseBriefDto" - "503": - description: Failed to find queue information in broker service + "403": + description: Not allowed to view database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "502": - description: Connection to the broker service could not be established + "404": + description: Database could not be found content: application/json: schema: @@ -2822,23 +2620,17 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: - "403": - description: Not the table owner. - content: - application/json: - schema: - $ref: "#/components/schemas/ApiErrorDto" - "422": - description: Ontology does not have rdf or sparql endpoint + "417": + description: Generated query is malformed content: application/json: schema: @@ -2851,8 +2643,8 @@ paths: type: array items: $ref: "#/components/schemas/EntityDto" - "417": - description: Generated query is malformed + "400": + description: Failed to parse statistic in search service content: application/json: schema: @@ -2863,8 +2655,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "400": - description: Failed to parse statistic in search service + "422": + description: Ontology does not have rdf or sparql endpoint + content: + application/json: + schema: + $ref: "#/components/schemas/ApiErrorDto" + "403": + description: Not the table owner. content: application/json: schema: @@ -2884,23 +2682,23 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: columnId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: - "422": - description: Ontology does not have rdf or sparql endpoint + "400": + description: Generated query is malformed content: application/json: schema: @@ -2913,14 +2711,14 @@ paths: type: array items: $ref: "#/components/schemas/TableColumnEntityDto" - "400": - description: Generated query is malformed + "404": + description: Failed to find database/table in metadata database content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "404": - description: Failed to find database/table in metadata database + "422": + description: Ontology does not have rdf or sparql endpoint content: application/json: schema: @@ -2940,21 +2738,21 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: - "404": - description: Container image could not be found + "200": + description: Found container content: application/json: schema: - $ref: "#/components/schemas/ApiErrorDto" - "200": - description: Found container + $ref: "#/components/schemas/ContainerDto" + "404": + description: Container image could not be found content: application/json: schema: - $ref: "#/components/schemas/ContainerDto" + $ref: "#/components/schemas/ApiErrorDto" delete: tags: - container-endpoint @@ -2966,8 +2764,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: "403": description: "Create container not permitted, need authority `delete-container`" @@ -2975,14 +2773,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" + "202": + description: Deleted container "404": description: Container not found content: application/json: schema: $ref: "#/components/schemas/ApiErrorDto" - "202": - description: Deleted container security: - bearerAuth: [] - basicAuth: [] @@ -3004,6 +2802,145 @@ paths: $ref: "#/components/schemas/ConceptDto" components: schemas: + ApiErrorDto: + required: + - code + - message + - status + type: object + properties: + status: + type: string + example: NOT_FOUND + enum: + - 100 CONTINUE + - 101 SWITCHING_PROTOCOLS + - 102 PROCESSING + - 103 EARLY_HINTS + - 103 CHECKPOINT + - 200 OK + - 201 CREATED + - 202 ACCEPTED + - 203 NON_AUTHORITATIVE_INFORMATION + - 204 NO_CONTENT + - 205 RESET_CONTENT + - 206 PARTIAL_CONTENT + - 207 MULTI_STATUS + - 208 ALREADY_REPORTED + - 226 IM_USED + - 300 MULTIPLE_CHOICES + - 301 MOVED_PERMANENTLY + - 302 FOUND + - 302 MOVED_TEMPORARILY + - 303 SEE_OTHER + - 304 NOT_MODIFIED + - 305 USE_PROXY + - 307 TEMPORARY_REDIRECT + - 308 PERMANENT_REDIRECT + - 400 BAD_REQUEST + - 401 UNAUTHORIZED + - 402 PAYMENT_REQUIRED + - 403 FORBIDDEN + - 404 NOT_FOUND + - 405 METHOD_NOT_ALLOWED + - 406 NOT_ACCEPTABLE + - 407 PROXY_AUTHENTICATION_REQUIRED + - 408 REQUEST_TIMEOUT + - 409 CONFLICT + - 410 GONE + - 411 LENGTH_REQUIRED + - 412 PRECONDITION_FAILED + - 413 PAYLOAD_TOO_LARGE + - 413 REQUEST_ENTITY_TOO_LARGE + - 414 URI_TOO_LONG + - 414 REQUEST_URI_TOO_LONG + - 415 UNSUPPORTED_MEDIA_TYPE + - 416 REQUESTED_RANGE_NOT_SATISFIABLE + - 417 EXPECTATION_FAILED + - 418 I_AM_A_TEAPOT + - 419 INSUFFICIENT_SPACE_ON_RESOURCE + - 420 METHOD_FAILURE + - 421 DESTINATION_LOCKED + - 422 UNPROCESSABLE_ENTITY + - 423 LOCKED + - 424 FAILED_DEPENDENCY + - 425 TOO_EARLY + - 426 UPGRADE_REQUIRED + - 428 PRECONDITION_REQUIRED + - 429 TOO_MANY_REQUESTS + - 431 REQUEST_HEADER_FIELDS_TOO_LARGE + - 451 UNAVAILABLE_FOR_LEGAL_REASONS + - 500 INTERNAL_SERVER_ERROR + - 501 NOT_IMPLEMENTED + - 502 BAD_GATEWAY + - 503 SERVICE_UNAVAILABLE + - 504 GATEWAY_TIMEOUT + - 505 HTTP_VERSION_NOT_SUPPORTED + - 506 VARIANT_ALSO_NEGOTIATES + - 507 INSUFFICIENT_STORAGE + - 508 LOOP_DETECTED + - 509 BANDWIDTH_LIMIT_EXCEEDED + - 510 NOT_EXTENDED + - 511 NETWORK_AUTHENTICATION_REQUIRED + message: + type: string + example: Error message + code: + type: string + example: error.service.code + UserAttributesDto: + required: + - language + - theme + type: object + properties: + theme: + type: string + example: light + orcid: + type: string + example: https://orcid.org/0000-0002-1825-0097 + affiliation: + type: string + example: Brown University + language: + type: string + example: en + UserDto: + required: + - attributes + - id + - password + - username + type: object + properties: + id: + type: string + format: uuid + example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 + name: + type: string + example: Josiah Carberry + username: + type: string + example: username + password: + type: string + example: p4ssw0rd + attributes: + $ref: "#/components/schemas/UserAttributesDto" + last_retrieved: + type: string + format: date-time + qualified_name: + type: string + example: Josiah Carberry — @jcarberry + given_name: + type: string + example: Josiah + family_name: + type: string + example: Carberry CreatorBriefDto: required: - creator_name @@ -3011,9 +2948,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 11 + type: string + format: uuid + example: e41f94a6-2b94-4a12-ac0e-678684e1c070 affiliation: type: string example: Brown University @@ -3060,9 +2997,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 3 + type: string + format: uuid + example: fc29f89c-86a8-4020-9e36-4d954736c6cc name: type: string example: Air Quality @@ -3094,6 +3031,7 @@ components: required: - creators - database_id + - descriptions - id - owned_by - publication_year @@ -3104,9 +3042,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: b97cd56b-66ca-4354-9e6c-f47210cfaaec type: type: string example: database @@ -3123,6 +3061,10 @@ components: type: array items: $ref: "#/components/schemas/IdentifierTitleDto" + descriptions: + type: array + items: + $ref: "#/components/schemas/IdentifierDescriptionDto" doi: type: string example: 10.1038/nphys1170 @@ -3136,21 +3078,18 @@ components: - draft - published database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: fc29f89c-86a8-4020-9e36-4d954736c6cc query_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid table_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid view_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid publication_year: type: integer format: int32 @@ -3159,18 +3098,18 @@ components: type: string format: uuid example: 2f45ef7a-7f9b-4667-9156-152c87fe1ca5 - IdentifierTitleDto: + IdentifierDescriptionDto: required: - id type: object properties: id: - type: integer - format: int64 - example: 4 - title: type: string - example: Airquality Demonstrator + format: uuid + example: e0e9692c-910b-4b60-b53a-fc7c358a917d + description: + type: string + example: "Air quality reports at Stephansplatz, Vienna" language: type: string example: en @@ -3361,570 +3300,29 @@ components: - zu type: type: string + example: Abstract enum: - - AlternativeTitle - - Subtitle - - TranslatedTitle + - Abstract + - Methods + - SeriesInformation + - TableOfContents + - TechnicalInfo - Other - UserBriefDto: + IdentifierTitleDto: required: - id - - username type: object properties: id: type: string format: uuid - example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 - username: - type: string - description: Only contains lowercase characters - example: jcarberry - name: - type: string - example: Josiah Carberry - orcid: - type: string - example: 0000-0002-1825-0097 - qualified_name: - type: string - example: Josiah Carberry — @jcarberry - given_name: - type: string - example: Josiah - family_name: + example: 70ce5164-fd74-413f-8712-f996b91defbf + title: type: string - example: Carberry - DatabaseAccessDto: - required: - - type - - user - type: object - properties: - user: - $ref: "#/components/schemas/UserBriefDto" - type: - type: string - example: read - enum: - - read - - write_own - - write_all - ApiErrorDto: - required: - - code - - message - - status - type: object - properties: - status: - type: string - example: NOT_FOUND - enum: - - 100 CONTINUE - - 101 SWITCHING_PROTOCOLS - - 102 PROCESSING - - 103 EARLY_HINTS - - 103 CHECKPOINT - - 200 OK - - 201 CREATED - - 202 ACCEPTED - - 203 NON_AUTHORITATIVE_INFORMATION - - 204 NO_CONTENT - - 205 RESET_CONTENT - - 206 PARTIAL_CONTENT - - 207 MULTI_STATUS - - 208 ALREADY_REPORTED - - 226 IM_USED - - 300 MULTIPLE_CHOICES - - 301 MOVED_PERMANENTLY - - 302 FOUND - - 302 MOVED_TEMPORARILY - - 303 SEE_OTHER - - 304 NOT_MODIFIED - - 305 USE_PROXY - - 307 TEMPORARY_REDIRECT - - 308 PERMANENT_REDIRECT - - 400 BAD_REQUEST - - 401 UNAUTHORIZED - - 402 PAYMENT_REQUIRED - - 403 FORBIDDEN - - 404 NOT_FOUND - - 405 METHOD_NOT_ALLOWED - - 406 NOT_ACCEPTABLE - - 407 PROXY_AUTHENTICATION_REQUIRED - - 408 REQUEST_TIMEOUT - - 409 CONFLICT - - 410 GONE - - 411 LENGTH_REQUIRED - - 412 PRECONDITION_FAILED - - 413 PAYLOAD_TOO_LARGE - - 413 REQUEST_ENTITY_TOO_LARGE - - 414 URI_TOO_LONG - - 414 REQUEST_URI_TOO_LONG - - 415 UNSUPPORTED_MEDIA_TYPE - - 416 REQUESTED_RANGE_NOT_SATISFIABLE - - 417 EXPECTATION_FAILED - - 418 I_AM_A_TEAPOT - - 419 INSUFFICIENT_SPACE_ON_RESOURCE - - 420 METHOD_FAILURE - - 421 DESTINATION_LOCKED - - 422 UNPROCESSABLE_ENTITY - - 423 LOCKED - - 424 FAILED_DEPENDENCY - - 425 TOO_EARLY - - 426 UPGRADE_REQUIRED - - 428 PRECONDITION_REQUIRED - - 429 TOO_MANY_REQUESTS - - 431 REQUEST_HEADER_FIELDS_TOO_LARGE - - 451 UNAVAILABLE_FOR_LEGAL_REASONS - - 500 INTERNAL_SERVER_ERROR - - 501 NOT_IMPLEMENTED - - 502 BAD_GATEWAY - - 503 SERVICE_UNAVAILABLE - - 504 GATEWAY_TIMEOUT - - 505 HTTP_VERSION_NOT_SUPPORTED - - 506 VARIANT_ALSO_NEGOTIATES - - 507 INSUFFICIENT_STORAGE - - 508 LOOP_DETECTED - - 509 BANDWIDTH_LIMIT_EXCEEDED - - 510 NOT_EXTENDED - - 511 NETWORK_AUTHENTICATION_REQUIRED - message: - type: string - example: Error message - code: - type: string - example: error.service.code - UserUpdateDto: - required: - - language - - theme - type: object - properties: - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Brown University - orcid: - type: string - example: 0000-0002-1825-0097 - theme: - type: string - example: dark - language: - type: string - example: en - UserAttributesDto: - required: - - language - - theme - type: object - properties: - theme: - type: string - example: light - orcid: - type: string - example: https://orcid.org/0000-0002-1825-0097 - affiliation: - type: string - example: Brown University - language: - type: string - example: en - UserDto: - required: - - attributes - - id - - password - - username - type: object - properties: - id: - type: string - format: uuid - example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 - name: - type: string - example: Josiah Carberry - username: - type: string - example: username - password: - type: string - example: p4ssw0rd - attributes: - $ref: "#/components/schemas/UserAttributesDto" - last_retrieved: - type: string - format: date-time - qualified_name: - type: string - example: Josiah Carberry — @jcarberry - given_name: - type: string - example: Josiah - family_name: - type: string - example: Carberry - UserPasswordDto: - required: - - password - type: object - properties: - password: - type: string - RefreshTokenRequestDto: - required: - - refresh_token - type: object - properties: - refresh_token: - type: string - example: refresh_token - TokenDto: - required: - - access_token - - expires_in - - id_token - - not-before-policy - - refresh_expires_in - - refresh_token - - scope - - session_state - - token_type - type: object - properties: - scope: - type: string - access_token: - type: string - expires_in: - type: integer - format: int64 - refresh_token: - type: string - refresh_expires_in: - type: integer - format: int64 - id_token: - type: string - session_state: - type: string - token_type: - type: string - not-before-policy: - type: integer - format: int64 - OntologyModifyDto: - required: - - prefix - - uri - type: object - properties: - uri: - type: string - example: Ontology URI - prefix: - type: string - example: Ontology prefix - sparql_endpoint: - type: string - example: Ontology SPARQL endpoint - rdf_path: - type: string - example: rdf/om-2.0.rdf - OntologyDto: - required: - - id - - prefix - - rdf - - sparql - - uri - type: object - properties: - id: - type: integer - format: int64 - uri: - type: string - example: http://www.wikidata.org/ - prefix: - type: string - example: wd - sparql: - type: boolean - example: true - rdf: - type: boolean - example: false - uri_pattern: - type: string - example: http://www.wikidata.org/entity/.* - sparql_endpoint: - type: string - example: https://query.wikidata.org/sparql - rdf_path: - type: string - example: rdf/om-2.0.rdf - BannerMessageUpdateDto: - required: - - message - - type - type: object - properties: - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: https://example.com - link_text: - type: string - example: More - display_start: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - display_end: - type: string - format: date-time - example: 2021-03-12T15:26:21Z - BannerMessageBriefDto: - required: - - message - - type - type: object - properties: - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: https://example.com - link_text: - type: string - example: More - ImageChangeDto: - required: - - dialect - - driver_class - - jdbc_method - - registry - type: object - properties: - registry: - type: string - example: docker.io/library - defaultPort: - maximum: 65535 - minimum: 1024 - type: integer - format: int32 - example: 5432 - dialect: - type: string - example: Postgres - driver_class: - type: string - example: org.postgresql.Driver - jdbc_method: - type: string - example: postgresql - DataTypeDto: - required: - - display_name - - documentation - - is_buildable - - is_quoted - - value - type: object - properties: - value: - type: string - example: time - documentation: - type: string - example: https://mariadb.com/kb/en/time/ - display_name: - type: string - example: TIME(fsp) - size_min: - type: integer - format: int32 - example: 0 - size_max: - type: integer - format: int32 - example: 6 - size_default: - type: integer - format: int32 - example: 0 - size_required: - type: boolean - example: false - d_min: - type: integer - format: int32 - d_max: - type: integer - format: int32 - d_default: - type: integer - format: int32 - d_required: - type: boolean - data_hint: - type: string - example: "e.g. HH:MM:SS, HH:MM, HHMMSS, H:M:S" - type_hint: - type: string - example: "fsp=microsecond precision, min. 0, max. 6" - is_quoted: - type: boolean - description: frontend needs to quote this data type - example: false - is_buildable: - type: boolean - description: frontend can build this data type - example: true - ImageDto: - required: - - data_types - - default - - default_port - - dialect - - driver_class - - id - - jdbc_method - - name - - operators - - registry - - version - type: object - properties: - id: - type: integer - format: int64 - example: 1 - registry: - type: string - example: docker.io/library - name: - type: string - example: mariadb - version: - type: string - example: "10.5" - dialect: - type: string - example: org.hibernate.dialect.MariaDBDialect - operators: - type: array - items: - $ref: "#/components/schemas/OperatorDto" - driver_class: - type: string - example: org.mariadb.jdbc.Driver - jdbc_method: - type: string - example: mariadb - default: - type: boolean - example: false - default_port: - type: integer - format: int32 - example: 3306 - data_types: - type: array - items: - $ref: "#/components/schemas/DataTypeDto" - OperatorDto: - required: - - display_name - - documentation - - value - type: object - properties: - id: - type: integer - format: int64 - value: - type: string - example: XOR - documentation: - type: string - example: https://mariadb.com/kb/en/xor/ - display_name: - type: string - example: XOR - IdentifierSaveDto: - required: - - creators - - database_id - - id - - publication_year - - publisher - - titles - - type - type: object - properties: - id: - type: integer - format: int64 - example: 1 - type: - type: string - example: database - enum: - - database - - subset - - table - - view - doi: - type: string - example: 10.1111/11111111 - titles: - type: array - items: - $ref: "#/components/schemas/SaveIdentifierTitleDto" - descriptions: - type: array - items: - $ref: "#/components/schemas/SaveIdentifierDescriptionDto" - funders: - type: array - items: - $ref: "#/components/schemas/SaveIdentifierFunderDto" - licenses: - type: array - items: - $ref: "#/components/schemas/LicenseDto" - publisher: - type: string - example: TU Wien - language: + example: Airquality Demonstrator + language: type: string + example: en enum: - ab - aa @@ -4110,122 +3508,371 @@ components: - yo - za - zu - creators: - type: array - items: - $ref: "#/components/schemas/SaveIdentifierCreatorDto" - database_id: + type: + type: string + enum: + - AlternativeTitle + - Subtitle + - TranslatedTitle + - Other + UserBriefDto: + required: + - id + - username + type: object + properties: + id: + type: string + format: uuid + example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 + username: + type: string + description: Only contains lowercase characters + example: jcarberry + name: + type: string + example: Josiah Carberry + orcid: + type: string + example: 0000-0002-1825-0097 + qualified_name: + type: string + example: Josiah Carberry — @jcarberry + given_name: + type: string + example: Josiah + family_name: + type: string + example: Carberry + DatabaseAccessDto: + required: + - type + - user + type: object + properties: + user: + $ref: "#/components/schemas/UserBriefDto" + type: + type: string + example: read + enum: + - read + - write_own + - write_all + UserUpdateDto: + required: + - language + - theme + type: object + properties: + firstname: + type: string + example: Josiah + lastname: + type: string + example: Carberry + affiliation: + type: string + example: Brown University + orcid: + type: string + example: 0000-0002-1825-0097 + theme: + type: string + example: dark + language: + type: string + example: en + OntologyModifyDto: + required: + - prefix + - uri + type: object + properties: + uri: + type: string + example: Ontology URI + prefix: + type: string + example: Ontology prefix + sparql_endpoint: + type: string + example: Ontology SPARQL endpoint + rdf_path: + type: string + example: rdf/om-2.0.rdf + OntologyDto: + required: + - id + - prefix + - rdf + - sparql + - uri + type: object + properties: + id: + type: string + format: uuid + example: 7c491e40-082a-47b8-b82c-51d03c520466 + uri: + type: string + example: http://www.wikidata.org/ + prefix: + type: string + example: wd + sparql: + type: boolean + example: true + rdf: + type: boolean + example: false + uri_pattern: + type: string + example: http://www.wikidata.org/entity/.* + sparql_endpoint: + type: string + example: https://query.wikidata.org/sparql + rdf_path: + type: string + example: rdf/om-2.0.rdf + BannerMessageUpdateDto: + required: + - message + - type + type: object + properties: + type: + type: string + enum: + - error + - warning + - info + message: + type: string + example: Maintenance starts on 8am on Monday + link: + type: string + example: https://example.com + link_text: + type: string + example: More + display_start: + type: string + format: date-time + example: 2021-03-12T15:26:21Z + display_end: + type: string + format: date-time + example: 2021-03-12T15:26:21Z + BannerMessageBriefDto: + required: + - message + - type + type: object + properties: + type: + type: string + enum: + - error + - warning + - info + message: + type: string + example: Maintenance starts on 8am on Monday + link: + type: string + example: https://example.com + link_text: + type: string + example: More + ImageChangeDto: + required: + - dialect + - driver_class + - jdbc_method + - registry + type: object + properties: + registry: + type: string + example: docker.io/library + defaultPort: + maximum: 65535 + minimum: 1024 type: integer - format: int64 - example: 1 - query_id: + format: int32 + example: 5432 + dialect: + type: string + example: Postgres + driver_class: + type: string + example: org.postgresql.Driver + jdbc_method: + type: string + example: postgresql + DataTypeDto: + required: + - display_name + - documentation + - id + - is_buildable + - is_quoted + - value + type: object + properties: + id: + type: string + format: uuid + example: 816f55d5-1098-4f60-a4af-c8121c04dcca + value: + type: string + example: time + documentation: + type: string + example: https://mariadb.com/kb/en/time/ + display_name: + type: string + example: TIME(fsp) + size_min: type: integer - format: int64 - view_id: + format: int32 + example: 0 + size_max: type: integer - format: int64 - table_id: + format: int32 + example: 6 + size_default: type: integer - format: int64 - publication_day: + format: int32 + example: 0 + size_required: + type: boolean + example: false + d_min: type: integer format: int32 - example: 15 - publication_month: + d_max: type: integer format: int32 - example: 12 - publication_year: + d_default: type: integer format: int32 - example: 2022 - related_identifiers: - type: array - items: - $ref: "#/components/schemas/SaveRelatedIdentifierDto" - LicenseDto: + d_required: + type: boolean + data_hint: + type: string + example: "e.g. HH:MM:SS, HH:MM, HHMMSS, H:M:S" + type_hint: + type: string + example: "fsp=microsecond precision, min. 0, max. 6" + is_quoted: + type: boolean + description: frontend needs to quote this data type + example: false + is_buildable: + type: boolean + description: frontend can build this data type + example: true + ImageDto: required: - - identifier - - uri + - data_types + - default + - id + - name + - operators + - version type: object properties: - identifier: + id: type: string - example: MIT - uri: + format: uuid + example: 816f55d5-1098-4f60-a4af-c8121c04dcce + name: type: string - example: https://opensource.org/licenses/MIT - description: + example: mariadb + version: type: string - example: "A short and simple permissive license with conditions only requiring\ - \ preservation of copyright and license notices. Licensed works, modifications,\ - \ and larger works may be distributed under different terms and without\ - \ source code." - SaveIdentifierCreatorDto: + example: "10.5" + operators: + type: array + items: + $ref: "#/components/schemas/OperatorDto" + default: + type: boolean + example: false + data_types: + type: array + items: + $ref: "#/components/schemas/DataTypeDto" + OperatorDto: required: - - creator_name + - display_name + - documentation - id + - value type: object properties: id: - type: integer - format: int64 - example: 1 - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Wesleyan University - creator_name: - type: string - example: "Carberry, Josiah" - name_type: - type: string - example: Personal - enum: - - Personal - - Organizational - name_identifier: type: string - example: 0000-0002-1825-0097 - name_identifier_scheme: + format: uuid + example: 816f55d5-1098-4f60-a4af-c8121c04dccf + value: type: string - example: ORCID - enum: - - ORCID - - ROR - - ISNI - - GRID - affiliation_identifier: + example: XOR + documentation: type: string - example: https://ror.org/04d836q62 - affiliation_identifier_scheme: + example: https://mariadb.com/kb/en/xor/ + display_name: type: string - example: ROR - enum: - - ROR - - GRID - - ISNI - SaveIdentifierDescriptionDto: + example: XOR + IdentifierSaveDto: required: - - description + - creators + - database_id - id + - publication_year + - publisher + - titles + - type type: object properties: id: - type: integer - format: int64 - example: 1 - description: type: string - example: "Air quality reports at Stephansplatz, Vienna" + format: uuid + example: 68e11675-1e0f-4d24-a6d9-887ad1c4445d + type: + type: string + example: database + enum: + - database + - subset + - table + - view + doi: + type: string + example: 10.1111/11111111 + titles: + type: array + items: + $ref: "#/components/schemas/SaveIdentifierTitleDto" + descriptions: + type: array + items: + $ref: "#/components/schemas/SaveIdentifierDescriptionDto" + funders: + type: array + items: + $ref: "#/components/schemas/SaveIdentifierFunderDto" + licenses: + type: array + items: + $ref: "#/components/schemas/LicenseDto" + publisher: + type: string + example: TU Wien language: type: string - example: en enum: - ab - aa @@ -4411,63 +4058,118 @@ components: - yo - za - zu - type: + creators: + type: array + items: + $ref: "#/components/schemas/SaveIdentifierCreatorDto" + database_id: + type: string + format: uuid + query_id: + type: string + format: uuid + view_id: + type: string + format: uuid + table_id: + type: string + format: uuid + publication_day: + type: integer + format: int32 + example: 15 + publication_month: + type: integer + format: int32 + example: 12 + publication_year: + type: integer + format: int32 + example: 2022 + related_identifiers: + type: array + items: + $ref: "#/components/schemas/SaveRelatedIdentifierDto" + LicenseDto: + required: + - identifier + - uri + type: object + properties: + identifier: type: string - example: Abstract - enum: - - Abstract - - Methods - - SeriesInformation - - TableOfContents - - TechnicalInfo - - Other - SaveIdentifierFunderDto: + example: MIT + uri: + type: string + example: https://opensource.org/licenses/MIT + description: + type: string + example: "A short and simple permissive license with conditions only requiring\ + \ preservation of copyright and license notices. Licensed works, modifications,\ + \ and larger works may be distributed under different terms and without\ + \ source code." + SaveIdentifierCreatorDto: required: - - funder_name + - creator_name - id type: object properties: id: - type: integer - format: int64 - example: 1 - funder_name: type: string - example: European Commission - funder_identifier: + format: uuid + example: da9dd034-00a8-4517-b93d-d1b2adfee418 + firstname: type: string - example: http://doi.org/10.13039/501100000780 - funder_identifier_type: + example: Josiah + lastname: type: string - example: Crossref Funder ID + example: Carberry + affiliation: + type: string + example: Wesleyan University + creator_name: + type: string + example: "Carberry, Josiah" + name_type: + type: string + example: Personal enum: - - Crossref Funder ID + - Personal + - Organizational + name_identifier: + type: string + example: 0000-0002-1825-0097 + name_identifier_scheme: + type: string + example: ORCID + enum: + - ORCID - ROR - - GND - ISNI - - Other - scheme_uri: - type: string - example: http://doi.org/ - award_number: + - GRID + affiliation_identifier: type: string - example: "824087" - award_title: + example: https://ror.org/04d836q62 + affiliation_identifier_scheme: type: string - example: EOSC-Life - SaveIdentifierTitleDto: + example: ROR + enum: + - ROR + - GRID + - ISNI + SaveIdentifierDescriptionDto: required: + - description - id - - title type: object properties: id: - type: integer - format: int64 - example: 1 - title: type: string - example: Airquality Demonstrator + format: uuid + example: 35bd84d8-b181-43c8-b786-4d024e4f843c + description: + type: string + example: "Air quality reports at Stephansplatz, Vienna" language: type: string example: en @@ -4658,154 +4360,61 @@ components: - zu type: type: string - example: Subtitle + example: Abstract enum: - - AlternativeTitle - - Subtitle - - TranslatedTitle + - Abstract + - Methods + - SeriesInformation + - TableOfContents + - TechnicalInfo - Other - SaveRelatedIdentifierDto: - required: - - id - - relation - - type - - value - type: object - properties: - id: - type: integer - format: int64 - example: 1 - value: - type: string - example: 10.70124/dc4zh-9ce78 - type: - type: string - example: DOI - enum: - - DOI - - URL - - URN - - ARK - - arXiv - - bibcode - - EAN13 - - EISSN - - Handle - - IGSN - - ISBN - - ISTC - - LISSN - - LSID - - PMID - - PURL - - UPC - - w3id - relation: - type: string - example: Cites - enum: - - IsCitedBy - - Cites - - IsSupplementTo - - IsSupplementedBy - - IsContinuedBy - - Continues - - IsDescribedBy - - Describes - - HasMetadata - - IsMetadataFor - - HasVersion - - IsVersionOf - - IsNewVersionOf - - IsPreviousVersionOf - - IsPartOf - - HasPart - - IsPublishedIn - - IsReferencedBy - - References - - IsDocumentedBy - - Documents - - IsCompiledBy - - Compiles - - IsVariantFormOf - - IsOriginalFormOf - - IsIdenticalTo - - IsReviewedBy - - Reviews - - IsDerivedFrom - - IsSourceOf - - IsRequiredBy - - Requires - - IsObsoletedBy - - Obsoletes - CreatorDto: + SaveIdentifierFunderDto: required: - - creator_name + - funder_name - id type: object properties: id: - type: integer - format: int64 - example: 11 - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: type: string - example: Brown University - creator_name: - type: string - example: "Carberry, Josiah" - name_type: + format: uuid + example: 1c6b9212-a315-44b9-946c-3682a7a0e517 + funder_name: type: string - example: Personal - enum: - - Personal - - Organizational - name_identifier: + example: European Commission + funder_identifier: type: string - example: 0000-0002-1825-0097 - name_identifier_scheme: + example: http://doi.org/10.13039/501100000780 + funder_identifier_type: type: string - example: ORCID + example: Crossref Funder ID enum: - - ORCID + - Crossref Funder ID - ROR + - GND - ISNI - - GRID - name_identifier_scheme_uri: - type: string - example: https://orcid.org/ - affiliation_identifier: + - Other + scheme_uri: type: string - example: https://ror.org/05gq02987 - affiliation_identifier_scheme: + example: http://doi.org/ + award_number: type: string - example: ROR - enum: - - ROR - - GRID - - ISNI - affiliation_identifier_scheme_uri: + example: "824087" + award_title: type: string - example: https://ror.org/ - IdentifierDescriptionDto: + example: EOSC-Life + SaveIdentifierTitleDto: required: - id + - title type: object properties: id: - type: integer - format: int64 - example: 3 - description: type: string - example: "Air quality reports at Stephansplatz, Vienna" + format: uuid + example: 2af9f40e-eaf5-4ea1-861a-1a696587bf29 + title: + type: string + example: Airquality Demonstrator language: type: string example: en @@ -4996,14 +4605,142 @@ components: - zu type: type: string - example: Abstract + example: Subtitle + enum: + - AlternativeTitle + - Subtitle + - TranslatedTitle + - Other + SaveRelatedIdentifierDto: + required: + - id + - relation + - type + - value + type: object + properties: + id: + type: string + format: uuid + example: 5bb272c7-7421-4f74-83ac-0486812d0f44 + value: + type: string + example: 10.70124/dc4zh-9ce78 + type: + type: string + example: DOI enum: - - Abstract - - Methods - - SeriesInformation - - TableOfContents - - TechnicalInfo - - Other + - DOI + - URL + - URN + - ARK + - arXiv + - bibcode + - EAN13 + - EISSN + - Handle + - IGSN + - ISBN + - ISTC + - LISSN + - LSID + - PMID + - PURL + - UPC + - w3id + relation: + type: string + example: Cites + enum: + - IsCitedBy + - Cites + - IsSupplementTo + - IsSupplementedBy + - IsContinuedBy + - Continues + - IsDescribedBy + - Describes + - HasMetadata + - IsMetadataFor + - HasVersion + - IsVersionOf + - IsNewVersionOf + - IsPreviousVersionOf + - IsPartOf + - HasPart + - IsPublishedIn + - IsReferencedBy + - References + - IsDocumentedBy + - Documents + - IsCompiledBy + - Compiles + - IsVariantFormOf + - IsOriginalFormOf + - IsIdenticalTo + - IsReviewedBy + - Reviews + - IsDerivedFrom + - IsSourceOf + - IsRequiredBy + - Requires + - IsObsoletedBy + - Obsoletes + CreatorDto: + required: + - creator_name + - id + type: object + properties: + id: + type: string + format: uuid + example: e41f94a6-2b94-4a12-ac0e-678684e1c070 + firstname: + type: string + example: Josiah + lastname: + type: string + example: Carberry + affiliation: + type: string + example: Brown University + creator_name: + type: string + example: "Carberry, Josiah" + name_type: + type: string + example: Personal + enum: + - Personal + - Organizational + name_identifier: + type: string + example: 0000-0002-1825-0097 + name_identifier_scheme: + type: string + example: ORCID + enum: + - ORCID + - ROR + - ISNI + - GRID + name_identifier_scheme_uri: + type: string + example: https://orcid.org/ + affiliation_identifier: + type: string + example: https://ror.org/05gq02987 + affiliation_identifier_scheme: + type: string + example: ROR + enum: + - ROR + - GRID + - ISNI + affiliation_identifier_scheme_uri: + type: string + example: https://ror.org/ IdentifierDto: required: - creators @@ -5025,9 +4762,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: b97cd56b-66ca-4354-9e6c-f47210cfaaec type: type: string example: database @@ -5266,21 +5003,17 @@ components: - draft - published database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid query_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid table_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid view_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid query_normalized: type: string example: "SELECT `id`, `value`, `location` FROM `air_quality` WHERE `location`\ @@ -5318,9 +5051,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: 39693413-e0ce-46da-ad5e-029c0556d439 funder_name: type: string example: European Commission @@ -5354,9 +5087,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 8 + type: string + format: uuid + example: ce9d11f0-60a2-448d-a3e4-44719a443e8a value: type: string example: 10.70124/dc4zh-9ce78 @@ -5455,9 +5188,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 4 + type: string + format: uuid + example: 787439d0-e85e-400c-a7e6-996a023bfad9 name: type: string example: Air Quality @@ -5465,9 +5198,9 @@ components: type: string example: SELECT `id` FROM `air_quality` ORDER BY `value` DESC database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: 2b5b2b03-fdd0-40d6-afe0-e5d02fd839e4 internal_name: type: string example: air_quality @@ -5518,9 +5251,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 3 + type: string + format: uuid + example: 41ed10e0-687b-4e18-8521-810f5cffbce1 name: type: string example: Air Quality @@ -5528,9 +5261,9 @@ components: type: string example: Air Quality in Austria database_id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: a8fec026-dfaf-4b1d-8f6c-f01720d91705 internal_name: type: string example: air_quality @@ -5567,9 +5300,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: a453e444-e00d-41ca-902c-11e9c54b39f1 name: maxLength: 64 minLength: 0 @@ -5603,26 +5336,20 @@ components: example: Column comment enums: type: array - example: - - val1 items: - type: string - example: "[\"val1\"]" + $ref: "#/components/schemas/EnumDto" sets: type: array - example: - - val1 items: - type: string - example: "[\"val1\"]" + $ref: "#/components/schemas/SetDto" database_id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: 911f9052-c58c-4e1c-b3f2-66af2107be16 table_id: - type: integer - format: int64 - example: 3 + type: string + format: uuid + example: bfffa915-a547-4466-9c65-ddc0d38fdb08 ord: type: integer format: int32 @@ -5705,9 +5432,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 23 + type: string + format: uuid + example: 8cabc011-4bdf-44d4-9d33-b2648e2ddbf1 uri: type: string example: http://www.wikidata.org/entity/Q202444 @@ -5718,6 +5445,32 @@ components: type: string example: "name typically used to differentiate people from the same family,\ \ clan, or other social group who have a common last name" + EnumDto: + required: + - id + - value + type: object + properties: + id: + type: string + format: uuid + example: 5343bb3d-14d3-4eb7-a86f-b8fc553cb315 + value: + type: string + example: "3" + SetDto: + required: + - id + - value + type: object + properties: + id: + type: string + format: uuid + example: 7eb4eded-bacc-4a91-84db-a9ae6ddafda7 + value: + type: string + example: "3" UnitBriefDto: required: - id @@ -5725,9 +5478,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 34 + type: string + format: uuid + example: ba1935e8-6817-488f-af0a-f54389af9000 uri: type: string example: http://www.wikidata.org/entity/Q1422583 @@ -5762,33 +5515,6 @@ components: - read - write_own - write_all - CreateUserDto: - required: - - email - - password - - username - type: object - properties: - username: - pattern: "^[a-z0-9]{3,}$" - type: string - example: user - email: - type: string - example: user@example.com - password: - type: string - LoginRequestDto: - required: - - password - - username - type: object - properties: - username: - type: string - example: user - password: - type: string OntologyCreateDto: required: - prefix @@ -6099,18 +5825,18 @@ components: items: $ref: "#/components/schemas/SaveIdentifierCreatorDto" database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: d002e8d5-8db4-4ff7-ab3a-bc3f52d9ec44 query_id: - type: integer - format: int64 - view_id: - type: integer - format: int64 + type: string + format: uuid + view_id: + type: string + format: uuid table_id: - type: integer - format: int64 + type: string + format: uuid publication_day: type: integer format: int32 @@ -6139,9 +5865,9 @@ components: type: string example: Air Quality container_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: 0888e108-d521-46e2-9d3e-82099185305b is_public: type: boolean example: true @@ -6162,14 +5888,79 @@ components: type: string example: Air Quality query: - type: string - example: SELECT `id` FROM `air_quality` + $ref: "#/components/schemas/SubsetDto" is_public: type: boolean example: true is_schema_public: type: boolean example: true + FilterDto: + required: + - column_id + - operator_id + - type + - value + type: object + properties: + type: + type: string + example: where + enum: + - where + - or + - and + value: + type: string + example: "1" + column_id: + type: string + format: uuid + example: 14128033-54b5-4818-a489-21b0dded86e2 + operator_id: + type: string + format: uuid + example: 67c5b54d-2eb0-4f42-8dc1-a504562e9f32 + OrderDto: + required: + - column_id + type: object + properties: + direction: + type: string + example: asc + enum: + - asc + - desc + column_id: + type: string + format: uuid + example: e891ba86-0258-41a6-a8d9-ff58bc10b618 + SubsetDto: + required: + - columns + - table_id + type: object + properties: + columns: + type: array + example: + - e891ba86-0258-41a6-a8d9-ff58bc10b618 + items: + type: string + format: uuid + filter: + type: array + items: + $ref: "#/components/schemas/FilterDto" + order: + type: array + items: + $ref: "#/components/schemas/OrderDto" + table_id: + type: string + format: uuid + example: f7df2a7d-4ade-4c78-97b0-7c744d0893c7 CreateForeignKeyDto: required: - columns @@ -6179,16 +5970,24 @@ components: properties: columns: type: array + example: + - id items: type: string + example: "[\"id\"]" referenced_table: type: string + example: sensor referenced_columns: type: array + example: + - other_id items: type: string + example: "[\"other_id\"]" on_update: type: string + example: cascade enum: - restrict - cascade @@ -6197,6 +5996,7 @@ components: - set_default on_delete: type: string + example: cascade enum: - restrict - cascade @@ -6215,7 +6015,7 @@ components: example: Date type: type: string - example: string + example: varchar enum: - char - varchar @@ -6368,10 +6168,10 @@ components: format: int64 example: 50 image_id: - type: integer + type: string description: Image ID - format: int64 - example: 1 + format: uuid + example: 2360f3c4-85e0-4fac-a7c6-73b296b9dde2 ui_host: type: string example: example.com @@ -6394,23 +6194,15 @@ components: - image - internal_name - name - - quota type: object properties: id: - type: integer - format: int64 - example: 4 + type: string + format: uuid + example: 7ddb7e87-b965-43a2-9a24-4fa406d998f4 name: type: string example: Air Quality - host: - type: string - example: data-db - port: - type: integer - format: int32 - example: 3306 image: $ref: "#/components/schemas/ImageDto" quota: @@ -6433,13 +6225,6 @@ components: internal_name: type: string example: air_quality - ui_host: - type: string - example: example.com - ui_port: - type: integer - format: int32 - example: 3306 ColumnBriefDto: required: - database_id @@ -6451,9 +6236,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: a453e444-e00d-41ca-902c-11e9c54b39f1 name: maxLength: 64 minLength: 0 @@ -6463,13 +6248,13 @@ components: type: string example: firstname database_id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: 911f9052-c58c-4e1c-b3f2-66af2107be16 table_id: - type: integer - format: int64 - example: 3 + type: string + format: uuid + example: bfffa915-a547-4466-9c65-ddc0d38fdb08 internal_name: maxLength: 64 minLength: 0 @@ -6517,8 +6302,9 @@ components: type: object properties: id: - type: integer - format: int64 + type: string + format: uuid + example: ba1935e8-6817-488f-af0a-f54389af9000 uri: type: string name: @@ -6539,8 +6325,9 @@ components: type: object properties: id: - type: integer - format: int64 + type: string + format: uuid + example: 7c491e40-082a-47b8-b82c-51d03c520466 uri: type: string example: http://www.wikidata.org/ @@ -6600,10 +6387,12 @@ components: type: object properties: id: - type: integer - format: int64 + type: string + format: uuid + example: ae3f795b-a3da-4ebe-bdc4-21a8ce631e6f type: type: string + example: WARNING enum: - error - warning @@ -6629,24 +6418,20 @@ components: required: - default - id - - jdbc_method - name - version type: object properties: id: - type: integer - format: int64 - example: 5 + type: string + format: uuid + example: 816f55d5-1098-4f60-a4af-c8121c04dcce name: type: string example: mariadb version: type: string example: "10.5" - jdbc_method: - type: string - example: mariadb default: type: boolean example: false @@ -6712,6 +6497,153 @@ components: type: string '@type': type: string + ViewColumnDto: + required: + - database_id + - id + - internal_name + - is_null_allowed + - name + - ord + - type + type: object + properties: + id: + type: string + format: uuid + example: 6aec3a91-2e0b-4e92-a16a-9c3c5e892da1 + name: + maxLength: 64 + minLength: 0 + type: string + example: Given Name + size: + type: integer + format: int64 + example: 255 + d: + type: integer + format: int64 + example: 0 + description: + maxLength: 2048 + minLength: 0 + type: string + example: Column comment + database_id: + type: string + format: uuid + example: 2b5b2b03-fdd0-40d6-afe0-e5d02fd839e4 + ord: + type: integer + format: int32 + example: 0 + internal_name: + maxLength: 64 + minLength: 0 + type: string + example: given_name + index_length: + type: integer + format: int64 + example: 255 + length: + type: integer + format: int64 + example: 255 + type: + type: string + example: varchar + enum: + - char + - varchar + - binary + - varbinary + - tinyblob + - tinytext + - text + - blob + - mediumtext + - mediumblob + - longtext + - longblob + - enum + - set + - serial + - bit + - tinyint + - bool + - smallint + - mediumint + - int + - bigint + - float + - double + - decimal + - date + - datetime + - timestamp + - time + - year + is_null_allowed: + type: boolean + example: false + ViewDto: + required: + - columns + - database_id + - id + - identifiers + - internal_name + - name + - owner + - query + - query_hash + type: object + properties: + id: + type: string + format: uuid + example: 787439d0-e85e-400c-a7e6-996a023bfad9 + name: + type: string + example: Air Quality + identifiers: + type: array + items: + $ref: "#/components/schemas/IdentifierDto" + query: + type: string + example: SELECT `id` FROM `air_quality` ORDER BY `value` DESC + owner: + $ref: "#/components/schemas/UserBriefDto" + columns: + type: array + items: + $ref: "#/components/schemas/ViewColumnDto" + last_retrieved: + type: string + format: date-time + database_id: + type: string + format: uuid + example: fc29f89c-86a8-4020-9e36-4d954736c6cc + internal_name: + type: string + example: air_quality + is_public: + type: boolean + example: true + is_schema_public: + type: boolean + example: true + initial_view: + type: boolean + description: True if it is the default view for the database + example: true + query_hash: + type: string + example: 7de03e818900b6ea6d58ad0306d4a741d658c6df3d1964e89ed2395d8c7e7916 ConstraintsDto: type: object properties: @@ -6736,86 +6668,13 @@ components: type: array items: $ref: "#/components/schemas/PrimaryKeyDto" - DatabaseDto: - required: - - accesses - - contact - - exchange_name - - id - - identifiers - - internal_name - - is_public - - is_schema_public - - name - - owner - - subsets - - tables - - views - type: object - properties: - id: - type: integer - format: int64 - example: 3 - name: - type: string - example: Air Quality - description: - type: string - example: Air Quality - tables: - type: array - items: - $ref: "#/components/schemas/TableDto" - views: - type: array - items: - $ref: "#/components/schemas/ViewDto" - container: - $ref: "#/components/schemas/ContainerDto" - accesses: - type: array - items: - $ref: "#/components/schemas/DatabaseAccessDto" - identifiers: - type: array - items: - $ref: "#/components/schemas/IdentifierDto" - subsets: - type: array - items: - $ref: "#/components/schemas/IdentifierDto" - contact: - $ref: "#/components/schemas/UserBriefDto" - owner: - $ref: "#/components/schemas/UserBriefDto" - last_retrieved: - type: string - format: date-time - exchange_name: - type: string - example: dbrepo - exchange_type: - type: string - example: topic - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - is_schema_public: - type: boolean - example: true - preview_image: - type: string ForeignKeyBriefDto: type: object properties: id: - type: integer - format: int64 - example: 8 + type: string + format: uuid + example: f2b740ec-0b13-4d07-88a9-529d354bba6a ForeignKeyDto: required: - name @@ -6825,9 +6684,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 4 + type: string + format: uuid + example: f2b740ec-0b13-4d07-88a9-529d354bba6a name: type: string example: fk_name @@ -6865,9 +6724,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 8 + type: string + format: uuid + example: f2b740ec-0b13-4d07-88a9-529d354bba6a column: $ref: "#/components/schemas/ColumnBriefDto" foreign_key: @@ -6881,9 +6740,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 8 + type: string + format: uuid + example: d984f9d7-e8a7-4b81-b59a-862db1871f18 table: $ref: "#/components/schemas/TableBriefDto" column: @@ -6905,9 +6764,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 3 + type: string + format: uuid + example: d346f844-b84c-490f-9aec-725a2dc8f820 name: type: string example: Air Quality @@ -6929,17 +6788,15 @@ components: type: array items: $ref: "#/components/schemas/ColumnDto" - database: - $ref: "#/components/schemas/DatabaseDto" constraints: $ref: "#/components/schemas/ConstraintsDto" last_retrieved: type: string format: date-time database_id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: fc29f89c-86a8-4020-9e36-4d954736c6cc internal_name: type: string example: air_quality @@ -6989,9 +6846,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 5 + type: string + format: uuid + example: d984f9d7-e8a7-4b81-b59a-862db1871f13 name: type: string example: uk_name @@ -7001,155 +6858,6 @@ components: type: array items: $ref: "#/components/schemas/ColumnBriefDto" - ViewColumnDto: - required: - - database_id - - id - - internal_name - - is_null_allowed - - name - - ord - - type - type: object - properties: - id: - type: integer - format: int64 - example: 12 - name: - maxLength: 64 - minLength: 0 - type: string - example: Given Name - size: - type: integer - format: int64 - example: 255 - d: - type: integer - format: int64 - example: 0 - description: - maxLength: 2048 - minLength: 0 - type: string - example: Column comment - database_id: - type: integer - format: int64 - example: 1 - ord: - type: integer - format: int32 - example: 0 - internal_name: - maxLength: 64 - minLength: 0 - type: string - example: given_name - index_length: - type: integer - format: int64 - example: 255 - length: - type: integer - format: int64 - example: 255 - type: - type: string - example: varchar - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - serial - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - is_null_allowed: - type: boolean - example: false - ViewDto: - required: - - columns - - database_id - - id - - identifiers - - internal_name - - name - - owner - - query - - query_hash - type: object - properties: - id: - type: integer - format: int64 - example: 4 - name: - type: string - example: Air Quality - identifiers: - type: array - items: - $ref: "#/components/schemas/IdentifierDto" - query: - type: string - example: SELECT `id` FROM `air_quality` ORDER BY `value` DESC - database: - $ref: "#/components/schemas/DatabaseDto" - owner: - $ref: "#/components/schemas/UserBriefDto" - columns: - type: array - items: - $ref: "#/components/schemas/ViewColumnDto" - last_retrieved: - type: string - format: date-time - database_id: - type: integer - format: int64 - example: 1 - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - is_schema_public: - type: boolean - example: true - initial_view: - type: boolean - description: True if it is the default view for the database - example: true - query_hash: - type: string - example: 7de03e818900b6ea6d58ad0306d4a741d658c6df3d1964e89ed2395d8c7e7916 TableColumnEntityDto: required: - column_id @@ -7168,17 +6876,17 @@ components: type: string example: open source semantic web framework for Java database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: 475b4107-a64d-4495-a7ef-3cb0dadd4804 table_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: 9a9208af-90ea-4382-9a11-0c8f6d89bd1f column_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: 297860e3-3b29-451c-ae8a-a85ed5941018 ContainerBriefDto: required: - count @@ -7191,9 +6899,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 4 + type: string + format: uuid + example: 7ddb7e87-b965-43a2-9a24-4fa406d998f4 hash: type: string example: f829dd8a884182d0da846f365dee1221fd16610a14c81b8f9f295ff162749e50 @@ -7221,8 +6929,9 @@ components: type: object properties: id: - type: integer - format: int64 + type: string + format: uuid + example: 8cabc011-4bdf-44d4-9d33-b2648e2ddbf1 uri: type: string name: diff --git a/.docs/.openapi/api.yaml b/.docs/.openapi/api.yaml index c23937c6e7..8c5ea7a152 100644 --- a/.docs/.openapi/api.yaml +++ b/.docs/.openapi/api.yaml @@ -16,7 +16,7 @@ info: name: Apache 2.0 url: 'https://www.apache.org/licenses/LICENSE-2.0' title: DBRepo REST API - version: 1.7.2 + version: 1.7.0 servers: - description: Test Instance url: 'https://test.dbrepo.tuwien.ac.at' @@ -153,22 +153,21 @@ paths: summary: Get view data description: >- Gets data from a view of a database. For private databases, the user - needs at least *READ* access to the associated database. Requires role - `view-database-view-data`. + needs at least *READ* access to the associated database. operationId: getData parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: page in: query required: false @@ -242,22 +241,21 @@ paths: summary: Get view data description: >- Gets data from a view of a database. For private databases, the user - needs at least *READ* access to the associated database. Requires role - `view-database-view-data`. + needs at least *READ* access to the associated database. operationId: getData_1 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: page in: query required: false @@ -341,14 +339,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -424,14 +422,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Authorization in: header required: true @@ -487,14 +485,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Authorization in: header required: true @@ -552,14 +550,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Authorization in: header required: true @@ -616,14 +614,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -702,14 +700,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: subsetId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -795,14 +793,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: subsetId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -884,14 +882,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: queryId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -956,14 +954,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Authorization in: header required: true @@ -1022,8 +1020,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: persisted in: query required: false @@ -1076,8 +1074,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -1100,7 +1098,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ExecuteStatementDto' + $ref: '#/components/schemas/SubsetDto' required: true responses: '201': @@ -1165,14 +1163,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -1229,14 +1227,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: size in: query required: false @@ -1294,14 +1292,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: timestamp in: query required: false @@ -1360,14 +1358,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: subsetId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Accept in: header required: true @@ -1422,101 +1420,131 @@ paths: security: - basicAuth: [] - bearerAuth: [] - /api/database: + '/api/user/{userId}': get: tags: - - database-endpoint - summary: List databases + - user-endpoint + summary: Get user description: >- - Lists all databases in the metadata database. Requests with HTTP method - **GET** return the list of databases, requests with HTTP method **HEAD** - only the number in the `X-Count` header. - operationId: list1 + Gets own user information from the metadata database. Requires + authentication. Foreign user information can only be obtained if + additional role `find-foreign-user` is present. Finding information + about internal users results in a 404 error. + operationId: find parameters: - - name: internal_name - in: query - required: false + - name: userId + in: path + required: true schema: type: string + format: uuid responses: '200': - description: List of databases - headers: - Access-Control-Expose-Headers: - description: Expose `X-Count` custom header - required: true - style: simple - X-Count: - description: Number of databases - required: true - style: simple + description: Found user content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/DatabaseBriefDto' - post: + $ref: '#/components/schemas/UserDto' + '403': + description: Find user is not permitted + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + '404': + description: User was not found + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + put: tags: - - database-endpoint - summary: Create database - description: >- - Creates a database in the container with id. Requires roles - `create-database`. - operationId: create_5 + - user-endpoint + summary: Update user + description: Updates user with id. Requires role `modify-user-information`. + operationId: modify + parameters: + - name: userId + in: path + required: true + schema: + type: string + format: uuid requestBody: content: application/json: schema: - $ref: '#/components/schemas/CreateDatabaseDto' + $ref: '#/components/schemas/UserUpdateDto' required: true responses: - '201': - description: Created a new database + '202': + description: Modified user information content: application/json: schema: - $ref: '#/components/schemas/DatabaseBriefDto' + $ref: '#/components/schemas/UserDto' '400': - description: Database create query is malformed or image is not supported + description: Modify user query is malformed content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' '403': - description: >- - Database create permission is missing or grant permissions at broker - service failed + description: Not allowed to modify user metadata content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' '404': - description: Failed to fin container/user/database in metadata database + description: Failed to find database/user in metadata database content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '409': - description: Query store could not be created + '503': + description: Failed to modify user at auth service content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '423': - description: Database quota exceeded + security: + - bearerAuth: [] + - basicAuth: [] + head: + tags: + - user-endpoint + summary: Get user + description: >- + Gets own user information from the metadata database. Requires + authentication. Foreign user information can only be obtained if + additional role `find-foreign-user` is present. Finding information + about internal users results in a 404 error. + operationId: find_1 + parameters: + - name: userId + in: path + required: true + schema: + type: string + format: uuid + responses: + '200': + description: Found user content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to search service failed + $ref: '#/components/schemas/UserDto' + '403': + description: Find user is not permitted content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to save in search service + '404': + description: User was not found content: application/json: schema: @@ -1524,7 +1552,109 @@ paths: security: - bearerAuth: [] - basicAuth: [] - head: + /api/database: + get: + tags: + - database-endpoint + summary: List databases + description: >- + Lists all databases in the metadata database. Requests with HTTP method + **GET** return the list of databases, requests with HTTP method **HEAD** + only the number in the `X-Count` header. + operationId: list1 + parameters: + - name: internal_name + in: query + required: false + schema: + type: string + responses: + '200': + description: List of databases + headers: + Access-Control-Expose-Headers: + description: Expose `X-Count` custom header + required: true + style: simple + X-Count: + description: Number of databases + required: true + style: simple + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DatabaseBriefDto' + post: + tags: + - database-endpoint + summary: Create database + description: >- + Creates a database in the container with id. Requires roles + `create-database`. + operationId: create_4 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CreateDatabaseDto' + required: true + responses: + '201': + description: Created a new database + content: + application/json: + schema: + $ref: '#/components/schemas/DatabaseBriefDto' + '400': + description: Database create query is malformed or image is not supported + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + '403': + description: >- + Database create permission is missing or grant permissions at broker + service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + '404': + description: Failed to fin container/user/database in metadata database + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + '409': + description: Query store could not be created + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + '423': + description: Database quota exceeded + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + '502': + description: Connection to search service failed + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + '503': + description: Failed to save in search service + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' + security: + - bearerAuth: [] + - basicAuth: [] + head: tags: - database-endpoint summary: List databases @@ -1568,14 +1698,14 @@ paths: with HTTP method **HEAD** only the status. When the user has at least *READ* access, the status 200 is returned, 403 otherwise. Requires role `check-database-access` or `check-foreign-database-access`. - operationId: find + operationId: find_2 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: userId in: path required: true @@ -1617,8 +1747,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: userId in: path required: true @@ -1678,14 +1808,14 @@ paths: description: >- Give a user with given id access to some database with given id. Requires role `create-database-access`. - operationId: create_8 + operationId: create_7 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: userId in: path required: true @@ -1751,8 +1881,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: userId in: path required: true @@ -1805,14 +1935,14 @@ paths: with HTTP method **HEAD** only the status. When the user has at least *READ* access, the status 200 is returned, 403 otherwise. Requires role `check-database-access` or `check-foreign-database-access`. - operationId: find_1 + operationId: find_3 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: userId in: path required: true @@ -1841,19 +1971,15 @@ paths: security: - bearerAuth: [] - basicAuth: [] - '/api/user/{userId}': + '/api/ontology/{ontologyId}': get: tags: - - user-endpoint - summary: Get user - description: >- - Gets own user information from the metadata database. Requires - authentication. Foreign user information can only be obtained if - additional role `find-foreign-user` is present. Finding information - about internal users results in a 404 error. - operationId: find_2 + - ontology-endpoint + summary: Find ontology + description: Finds an ontology with id in the metadata database. + operationId: find_4 parameters: - - name: userId + - name: ontologyId in: path required: true schema: @@ -1861,34 +1987,25 @@ paths: format: uuid responses: '200': - description: Found user - content: - application/json: - schema: - $ref: '#/components/schemas/UserDto' - '403': - description: Find user is not permitted + description: Find one ontology content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + $ref: '#/components/schemas/OntologyDto' '404': - description: User was not found + description: Could not find ontology content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] put: tags: - - user-endpoint - summary: Update user - description: Updates user with id. Requires role `modify-user-information`. - operationId: modify + - ontology-endpoint + summary: Update ontology + description: Updates an ontology with id. Requires role `update-ontology`. + operationId: update parameters: - - name: userId + - name: ontologyId in: path required: true schema: @@ -1898,29 +2015,44 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/UserUpdateDto' + $ref: '#/components/schemas/OntologyModifyDto' required: true responses: '202': - description: Modified user information + description: Updated ontology successfully content: application/json: schema: - $ref: '#/components/schemas/UserDto' - '400': - description: Modify user query is malformed + $ref: '#/components/schemas/OntologyDto' + '404': + description: Could not find ontology content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to modify user metadata + security: + - bearerAuth: [] + - basicAuth: [] + delete: + tags: + - ontology-endpoint + summary: Delete ontology + description: Deletes an ontology with given id. Requires role `delete-ontology`. + operationId: delete + parameters: + - name: ontologyId + in: path + required: true + schema: + type: string + format: uuid + responses: + '202': + description: Deleted ontology successfully content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' + application/json: {} '404': - description: Failed to find database/user in metadata database + description: Could not find ontology content: application/json: schema: @@ -1928,15 +2060,15 @@ paths: security: - bearerAuth: [] - basicAuth: [] - '/api/user/{userId}/password': + '/api/message/{messageId}': put: tags: - - user-endpoint - summary: Update user password - description: Updates password of user with id. Requires authentication. - operationId: password + - message-endpoint + summary: Update message + description: Updates a message with id. Requires role `update-maintenance-message`. + operationId: update_1 parameters: - - name: userId + - name: messageId in: path required: true schema: @@ -1946,37 +2078,44 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/UserPasswordDto' + $ref: '#/components/schemas/BannerMessageUpdateDto' required: true responses: '202': - description: Modified user password - '400': - description: Invalid password payload - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to change foreign user password + description: Updated message content: application/json: schema: - $ref: '#/components/schemas/ApiErrorDto' + $ref: '#/components/schemas/BannerMessageBriefDto' '404': - description: Failed to find database/user in metadata database + description: Could not find message content: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to auth service failed + security: + - bearerAuth: [] + - basicAuth: [] + delete: + tags: + - message-endpoint + summary: Delete message + description: Deletes a message with id. Requires role `delete-maintenance-message`. + operationId: delete_1 + parameters: + - name: messageId + in: path + required: true + schema: + type: string + format: uuid + responses: + '202': + description: Deleted message content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to get user in auth service + application/json: {} + '404': + description: Could not find message content: application/json: schema: @@ -1984,255 +2123,8 @@ paths: security: - bearerAuth: [] - basicAuth: [] - /api/user/token: - put: - tags: - - user-endpoint - summary: Refresh token - description: Refreshes user token by refresh token. - operationId: refreshToken - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/RefreshTokenRequestDto' - required: true - responses: - '202': - description: Refreshed user token - content: - application/json: - schema: - $ref: '#/components/schemas/TokenDto' - '400': - description: Invalid refresh token - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to auth service failed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - post: - tags: - - user-endpoint - summary: Create token - description: Creates a user token via the Auth Service. - operationId: getToken - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/LoginRequestDto' - required: true - responses: - '202': - description: Obtained user token - content: - application/json: - schema: - $ref: '#/components/schemas/TokenDto' - '400': - description: Invalid login request - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '403': - description: Not allowed to get token - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Failed to find user in auth database - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '428': - description: >- - Account is not fully setup in auth service (requires password - change?) - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to auth service failed - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to get user in auth service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '/api/ontology/{ontologyId}': - get: - tags: - - ontology-endpoint - summary: Find ontology - description: Finds an ontology with id in the metadata database. - operationId: find_3 - parameters: - - name: ontologyId - in: path - required: true - schema: - type: integer - format: int64 - responses: - '200': - description: Find one ontology - content: - application/json: - schema: - $ref: '#/components/schemas/OntologyDto' - '404': - description: Could not find ontology - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - put: - tags: - - ontology-endpoint - summary: Update ontology - description: Updates an ontology with id. Requires role `update-ontology`. - operationId: update - parameters: - - name: ontologyId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/OntologyModifyDto' - required: true - responses: - '202': - description: Updated ontology successfully - content: - application/json: - schema: - $ref: '#/components/schemas/OntologyDto' - '404': - description: Could not find ontology - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - ontology-endpoint - summary: Delete ontology - description: Deletes an ontology with given id. Requires role `delete-ontology`. - operationId: delete - parameters: - - name: ontologyId - in: path - required: true - schema: - type: integer - format: int64 - responses: - '202': - description: Deleted ontology successfully - content: - application/json: {} - '404': - description: Could not find ontology - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - '/api/message/{messageId}': - put: - tags: - - message-endpoint - summary: Update message - description: Updates a message with id. Requires role `update-maintenance-message`. - operationId: update_1 - parameters: - - name: messageId - in: path - required: true - schema: - type: integer - format: int64 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/BannerMessageUpdateDto' - required: true - responses: - '202': - description: Updated message - content: - application/json: - schema: - $ref: '#/components/schemas/BannerMessageBriefDto' - '404': - description: Could not find message - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - delete: - tags: - - message-endpoint - summary: Delete message - description: Deletes a message with id. Requires role `delete-maintenance-message`. - operationId: delete_1 - parameters: - - name: messageId - in: path - required: true - schema: - type: integer - format: int64 - responses: - '202': - description: Deleted message - content: - application/json: {} - '404': - description: Could not find message - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - security: - - bearerAuth: [] - - basicAuth: [] - '/api/image/{imageId}': - get: + '/api/image/{imageId}': + get: tags: - image-endpoint summary: Find image @@ -2243,8 +2135,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: Found image @@ -2271,8 +2163,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -2308,8 +2200,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '202': description: Deleted image successfully @@ -2330,14 +2222,14 @@ paths: description: >- Finds an identifier with id. The response format depends on the HTTP `Accept` header set on the request. - operationId: find_6 + operationId: find_7 parameters: - name: identifierId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: Accept in: header required: true @@ -2365,6 +2257,12 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' + '403': + description: Not allowed to view identifier + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' '404': description: Identifier could not be found content: @@ -2416,8 +2314,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -2475,8 +2373,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '202': description: Deleted identifier @@ -2521,8 +2419,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '202': description: Published identifier @@ -2577,8 +2475,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -2631,48 +2529,23 @@ paths: - view-endpoint summary: Get view description: Gets a view with id in the metadata database. - operationId: find_7 + operationId: find_8 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: Find view successfully - headers: - X-Username: - description: The authentication username - style: simple - Access-Control-Expose-Headers: - description: Expose custom headers - style: simple - X-Type: - description: The JDBC connection type - style: simple - X-View: - description: The view internal name - style: simple - X-Database: - description: The database internal name - style: simple - X-Password: - description: The authentication password - style: simple - X-Host: - description: The database hostname - style: simple - X-Port: - description: The database port number - style: simple content: application/json: schema: @@ -2705,14 +2578,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -2770,14 +2643,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: viewId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '202': description: Delete view successfully @@ -2836,27 +2709,17 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: Find table successfully - headers: - X-Username: - description: The authentication username - style: simple - Access-Control-Expose-Headers: - description: Expose custom headers - style: simple - X-Password: - description: The authentication password - style: simple content: application/json: schema: @@ -2873,18 +2736,6 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Failed to establish connection with broker service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to obtain queue information from broker service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' security: - bearerAuth: [] - basicAuth: [] @@ -2899,14 +2750,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -2967,14 +2818,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '202': description: Delete table successfully @@ -3026,14 +2877,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '202': description: Updated table statistics successfully @@ -3086,20 +2937,20 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: columnId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -3162,8 +3013,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -3225,8 +3076,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: Refreshed database views metadata @@ -3276,8 +3127,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: Refreshed database tables metadata @@ -3298,7 +3149,7 @@ paths: schema: $ref: '#/components/schemas/ApiErrorDto' '404': - description: Failed to fin user/database in metadata database + description: Failed to find database in metadata database content: application/json: schema: @@ -3330,8 +3181,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: View of image was successful @@ -3364,8 +3215,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -3412,93 +3263,6 @@ paths: security: - bearerAuth: [] - basicAuth: [] - /api/user: - get: - tags: - - user-endpoint - summary: List users - description: >- - Lists users known to the metadata database. Internal users are omitted - from the result list. If the optional query parameter `username` is - present, the result list can be filtered by matching this exact - username. - operationId: findAll - parameters: - - name: username - in: query - required: false - schema: - type: string - responses: - '200': - description: List users - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/UserBriefDto' - post: - tags: - - user-endpoint - summary: Create user - description: >- - Creates a user in the auth service and metadata database. Requires that - no credentials are sent in the request. - operationId: create1 - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/CreateUserDto' - required: true - responses: - '201': - description: Created user - content: - application/json: - schema: - $ref: '#/components/schemas/UserDto' - '400': - description: Parameters are not well-formed (likely email) - content: - application/json: {} - '403': - description: Internal authentication to the auth service is invalid - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '404': - description: Default role not found - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '409': - description: User with username already exists - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '417': - description: User with e-mail already exists - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Failed to create in auth service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to create in auth service - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' /api/ontology: get: tags: @@ -3522,7 +3286,7 @@ paths: description: >- Creates an ontology in the metadata database. Requires role `create-ontology`. - operationId: create_1 + operationId: create1 requestBody: content: application/json: @@ -3573,7 +3337,7 @@ paths: description: >- Creates a message in the metadata database. Requires role `create-maintenance-message`. - operationId: create_2 + operationId: create_1 requestBody: content: application/json: @@ -3613,7 +3377,7 @@ paths: description: >- Creates a container image in the metadata database. Requires role `create-image`. - operationId: create_3 + operationId: create_2 requestBody: content: application/json: @@ -3650,30 +3414,48 @@ paths: description: Lists all identifiers known to the metadata database operationId: findAll_4 parameters: + - name: type + in: query + required: false + schema: + type: string + enum: + - database + - subset + - table + - view + - name: status + in: query + required: false + schema: + type: string + enum: + - draft + - published - name: dbid in: query required: false schema: - type: integer - format: int64 + type: string + format: uuid - name: qid in: query required: false schema: - type: integer - format: int64 + type: string + format: uuid - name: vid in: query required: false schema: - type: integer - format: int64 + type: string + format: uuid - name: tid in: query required: false schema: - type: integer - format: int64 + type: string + format: uuid - name: Accept in: header required: true @@ -3693,12 +3475,6 @@ paths: type: array items: $ref: '#/components/schemas/LdDatasetDto' - '406': - description: 'Identifier could not be exported, the requested style is not known' - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' post: tags: - identifier-endpoint @@ -3708,7 +3484,7 @@ paths: can only be created for objects the user has at least *READ* access in the associated database (requires role `create-identifier`) or for any object in any database (requires role `create-foreign-identifier`). - operationId: create_4 + operationId: create_3 requestBody: content: application/json: @@ -3767,8 +3543,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: Find views successfully @@ -3794,14 +3570,14 @@ paths: description: >- Creates a view. This can only be performed by the database owner. Requires role `create-database-view`. - operationId: create_6 + operationId: create_5 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -3833,6 +3609,12 @@ paths: application/json: schema: $ref: '#/components/schemas/ApiErrorDto' + '409': + description: View exists with name + content: + application/json: + schema: + $ref: '#/components/schemas/ApiErrorDto' '423': description: Create view resulted in an invalid query statement content: @@ -3869,8 +3651,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: List tables @@ -3900,14 +3682,14 @@ paths: - table-endpoint summary: Create table description: Creates a table in the database with id. Requires role `create-table`. - operationId: create_7 + operationId: create_6 parameters: - name: databaseId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid requestBody: content: application/json: @@ -3990,7 +3772,7 @@ paths: description: >- Creates a container in the metadata database. Requires role `create-container`. - operationId: create_9 + operationId: create_8 requestBody: content: application/json: @@ -4031,6 +3813,32 @@ paths: security: - bearerAuth: [] - basicAuth: [] + /api/user: + get: + tags: + - user-endpoint + summary: List users + description: >- + Lists users known to the metadata database. Internal users are omitted + from the result list. If the optional query parameter `username` is + present, the result list can be filtered by matching this exact + username. + operationId: findAll + parameters: + - name: username + in: query + required: false + schema: + type: string + responses: + '200': + description: List users + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UserBriefDto' /api/unit: get: tags: @@ -4055,14 +3863,14 @@ paths: description: >- Finds semantic entities by label or uri in an ontology with id. Requires role `execute-semantic-query`. - operationId: find_4 + operationId: find_5 parameters: - name: ontologyId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: label in: query required: false @@ -4134,14 +3942,14 @@ paths: - message-endpoint summary: Find message description: Finds a message with id in the metadata database. - operationId: find_5 + operationId: find_6 parameters: - name: messageId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: Get messages @@ -4211,8 +4019,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: Database found successfully @@ -4237,19 +4045,7 @@ paths: schema: $ref: '#/components/schemas/ApiErrorDto' '404': - description: 'Database, user or exchange could not be found' - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '502': - description: Connection to the broker service could not be established - content: - application/json: - schema: - $ref: '#/components/schemas/ApiErrorDto' - '503': - description: Failed to find queue information in broker service + description: Database could not be found content: application/json: schema: @@ -4271,14 +4067,14 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: Suggested table semantics successfully @@ -4333,20 +4129,20 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: tableId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid - name: columnId in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: Suggested table column semantics successfully @@ -4389,8 +4185,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '200': description: Found container @@ -4417,8 +4213,8 @@ paths: in: path required: true schema: - type: integer - format: int64 + type: string + format: uuid responses: '202': description: Deleted container @@ -4826,9 +4622,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 11 + type: string + format: uuid + example: e41f94a6-2b94-4a12-ac0e-678684e1c070 affiliation: type: string example: Brown University @@ -4866,6 +4662,7 @@ components: required: - creators - database_id + - descriptions - id - owned_by - publication_year @@ -4876,9 +4673,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: b97cd56b-66ca-4354-9e6c-f47210cfaaec type: type: string example: database @@ -4895,6 +4692,10 @@ components: type: array items: $ref: '#/components/schemas/IdentifierTitleDto' + descriptions: + type: array + items: + $ref: '#/components/schemas/IdentifierDescriptionDto' doi: type: string example: 10.1038/nphys1170 @@ -4908,21 +4709,18 @@ components: - draft - published database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: fc29f89c-86a8-4020-9e36-4d954736c6cc query_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid table_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid view_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid publication_year: type: integer format: int32 @@ -4931,18 +4729,18 @@ components: type: string format: uuid example: 2f45ef7a-7f9b-4667-9156-152c87fe1ca5 - IdentifierTitleDto: + IdentifierDescriptionDto: required: - id type: object properties: id: - type: integer - format: int64 - example: 4 - title: type: string - example: Airquality Demonstrator + format: uuid + example: e0e9692c-910b-4b60-b53a-fc7c358a917d + description: + type: string + example: 'Air quality reports at Stephansplatz, Vienna' language: type: string example: en @@ -5133,119 +4931,329 @@ components: - zu type: type: string + example: Abstract enum: - - AlternativeTitle - - Subtitle - - TranslatedTitle + - Abstract + - Methods + - SeriesInformation + - TableOfContents + - TechnicalInfo - Other - QueryDto: - required: - - database_id - - execution - - id - - identifiers - - is_persisted - - owner - - query - - query_hash - - query_normalized - type: object - properties: - id: - type: integer - format: int64 - example: 4 - owner: - $ref: '#/components/schemas/UserBriefDto' - execution: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - query: - type: string - example: SELECT `id` FROM `air_quality` - type: - type: string - example: query - enum: - - query - - view - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierBriefDto' - database_id: - type: integer - format: int64 - example: 1 - query_normalized: - type: string - example: SELECT `id` FROM `air_quality` - query_hash: - type: string - example: 17e682f060b5f8e47ea04c5c4855908b0a5ad612022260fe50e11ecb0cc0ab76 - is_persisted: - type: boolean - example: true - result_hash: - type: string - example: 17e682f060b5f8e47ea04c5c4855908b0a5ad612022260fe50e11ecb0cc0ab76 - result_number: - type: integer - format: int64 - example: 1 - UserBriefDto: + IdentifierTitleDto: required: - id - - username type: object properties: id: type: string format: uuid - example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 - username: - type: string - description: Only contains lowercase characters - example: jcarberry - name: - type: string - example: Josiah Carberry - orcid: - type: string - example: 0000-0002-1825-0097 - qualified_name: - type: string - example: Josiah Carberry — @jcarberry - given_name: - type: string - example: Josiah - family_name: + example: 70ce5164-fd74-413f-8712-f996b91defbf + title: type: string - example: Carberry - TupleDto: - required: - - data - type: object - properties: - data: - type: object - additionalProperties: - type: object - example: - key: value - example: - key: value - ImportDto: - required: - - header - - location - - separator - type: object - properties: - location: + example: Airquality Demonstrator + language: type: string - example: file.csv + example: en + enum: + - ab + - aa + - af + - ak + - sq + - am + - ar + - an + - hy + - as + - av + - ae + - ay + - az + - bm + - ba + - eu + - be + - bn + - bh + - bi + - bs + - br + - bg + - my + - ca + - km + - ch + - ce + - ny + - zh + - cu + - cv + - kw + - co + - cr + - hr + - cs + - da + - dv + - nl + - dz + - en + - eo + - et + - ee + - fo + - fj + - fi + - fr + - ff + - gd + - gl + - lg + - ka + - de + - ki + - el + - kl + - gn + - gu + - ht + - ha + - he + - hz + - hi + - ho + - hu + - is + - io + - ig + - id + - ia + - ie + - iu + - ik + - ga + - it + - ja + - jv + - kn + - kr + - ks + - kk + - rw + - kv + - kg + - ko + - kj + - ku + - ky + - lo + - la + - lv + - lb + - li + - ln + - lt + - lu + - mk + - mg + - ms + - ml + - mt + - gv + - mi + - mr + - mh + - ro + - mn + - na + - nv + - nd + - ng + - ne + - se + - 'no' + - nb + - nn + - ii + - oc + - oj + - or + - om + - os + - pi + - pa + - ps + - fa + - pl + - pt + - qu + - rm + - rn + - ru + - sm + - sg + - sa + - sc + - sr + - sn + - sd + - si + - sk + - sl + - so + - st + - nr + - es + - su + - sw + - ss + - sv + - tl + - ty + - tg + - ta + - tt + - te + - th + - bo + - ti + - to + - ts + - tn + - tr + - tk + - tw + - ug + - uk + - ur + - uz + - ve + - vi + - vo + - wa + - cy + - fy + - wo + - xh + - yi + - yo + - za + - zu + type: + type: string + enum: + - AlternativeTitle + - Subtitle + - TranslatedTitle + - Other + QueryDto: + required: + - database_id + - execution + - id + - identifiers + - is_persisted + - owner + - query + - query_hash + - query_normalized + type: object + properties: + id: + type: string + format: uuid + example: 83ea2326-f8f6-4263-baf8-cdf88a54efc7 + owner: + $ref: '#/components/schemas/UserBriefDto' + execution: + type: string + format: date-time + example: '2021-03-12T15:26:21.000Z' + query: + type: string + example: SELECT `id` FROM `air_quality` + type: + type: string + example: query + enum: + - query + - view + identifiers: + type: array + items: + $ref: '#/components/schemas/IdentifierBriefDto' + database_id: + type: string + format: uuid + example: fc29f89c-86a8-4020-9e36-4d954736c6cc + query_normalized: + type: string + example: SELECT `id` FROM `air_quality` + query_hash: + type: string + example: 17e682f060b5f8e47ea04c5c4855908b0a5ad612022260fe50e11ecb0cc0ab76 + is_persisted: + type: boolean + example: true + result_hash: + type: string + example: 17e682f060b5f8e47ea04c5c4855908b0a5ad612022260fe50e11ecb0cc0ab76 + result_number: + type: integer + format: int64 + example: 1 + UserBriefDto: + required: + - id + - username + type: object + properties: + id: + type: string + format: uuid + example: 1ffc7b0e-9aeb-4e8b-b8f1-68f3936155b4 + username: + type: string + description: Only contains lowercase characters + example: jcarberry + name: + type: string + example: Josiah Carberry + orcid: + type: string + example: 0000-0002-1825-0097 + qualified_name: + type: string + example: Josiah Carberry — @jcarberry + given_name: + type: string + example: Josiah + family_name: + type: string + example: Carberry + TupleDto: + required: + - data + type: object + properties: + data: + type: object + additionalProperties: + type: object + example: + key: value + example: + key: value + ImportDto: + required: + - header + - location + - separator + type: object + properties: + location: + type: string + example: file.csv header: type: boolean description: >- @@ -5261,14 +5269,72 @@ components: line_termination: type: string example: \r\n - ExecuteStatementDto: + FilterDto: required: - - statement + - column_id + - operator_id + - type + - value type: object properties: - statement: + type: type: string - example: SELECT `id` FROM `air_quality` + example: where + enum: + - where + - or + - and + value: + type: string + example: '1' + column_id: + type: string + format: uuid + example: 14128033-54b5-4818-a489-21b0dded86e2 + operator_id: + type: string + format: uuid + example: 67c5b54d-2eb0-4f42-8dc1-a504562e9f32 + OrderDto: + required: + - column_id + type: object + properties: + direction: + type: string + example: asc + enum: + - asc + - desc + column_id: + type: string + format: uuid + example: e891ba86-0258-41a6-a8d9-ff58bc10b618 + SubsetDto: + required: + - columns + - table_id + type: object + properties: + columns: + type: array + example: + - e891ba86-0258-41a6-a8d9-ff58bc10b618 + items: + type: string + format: uuid + filter: + type: array + items: + $ref: '#/components/schemas/FilterDto' + order: + type: array + items: + $ref: '#/components/schemas/OrderDto' + table_id: + type: string + format: uuid + example: f7df2a7d-4ade-4c78-97b0-7c744d0893c7 TableHistoryDto: required: - event @@ -5282,6 +5348,10 @@ components: example: '2021-03-12T15:26:21.000Z' event: type: string + example: INSERT + enum: + - insert + - delete total: type: integer format: int64 @@ -5299,88 +5369,6 @@ components: id: 1 example: id: 1 - DatabaseBriefDto: - required: - - contact - - id - - identifiers - - internal_name - - is_public - - is_schema_public - - name - - owner_id - type: object - properties: - id: - type: integer - format: int64 - example: 3 - name: - type: string - example: Air Quality - description: - type: string - example: Air Quality - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierBriefDto' - contact: - $ref: '#/components/schemas/UserBriefDto' - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - is_schema_public: - type: boolean - example: true - owner_id: - type: string - format: uuid - example: 2f45ef7a-7f9b-4667-9156-152c87fe1ca5 - preview_image: - type: string - DatabaseAccessDto: - required: - - type - - user - type: object - properties: - user: - $ref: '#/components/schemas/UserBriefDto' - type: - type: string - example: read - enum: - - read - - write_own - - write_all - UserUpdateDto: - required: - - language - - theme - type: object - properties: - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Brown University - orcid: - type: string - example: 0000-0002-1825-0097 - theme: - type: string - example: dark - language: - type: string - example: en UserAttributesDto: required: - language @@ -5433,56 +5421,89 @@ components: example: Josiah family_name: type: string - example: Carberry - UserPasswordDto: - required: - - password - type: object - properties: - password: + example: Carberry + DatabaseBriefDto: + required: + - contact + - id + - identifiers + - internal_name + - is_public + - is_schema_public + - name + - owner_id + type: object + properties: + id: + type: string + format: uuid + example: fc29f89c-86a8-4020-9e36-4d954736c6cc + name: + type: string + example: Air Quality + description: + type: string + example: Air Quality + identifiers: + type: array + items: + $ref: '#/components/schemas/IdentifierBriefDto' + contact: + $ref: '#/components/schemas/UserBriefDto' + internal_name: + type: string + example: air_quality + is_public: + type: boolean + example: true + is_schema_public: + type: boolean + example: true + owner_id: + type: string + format: uuid + example: 2f45ef7a-7f9b-4667-9156-152c87fe1ca5 + preview_image: type: string - RefreshTokenRequestDto: + DatabaseAccessDto: required: - - refresh_token + - type + - user type: object properties: - refresh_token: + user: + $ref: '#/components/schemas/UserBriefDto' + type: type: string - example: refresh_token - TokenDto: + example: read + enum: + - read + - write_own + - write_all + UserUpdateDto: required: - - access_token - - expires_in - - id_token - - not-before-policy - - refresh_expires_in - - refresh_token - - scope - - session_state - - token_type + - language + - theme type: object properties: - scope: + firstname: type: string - access_token: + example: Josiah + lastname: type: string - expires_in: - type: integer - format: int64 - refresh_token: + example: Carberry + affiliation: type: string - refresh_expires_in: - type: integer - format: int64 - id_token: + example: Brown University + orcid: type: string - session_state: + example: 0000-0002-1825-0097 + theme: type: string - token_type: + example: dark + language: type: string - not-before-policy: - type: integer - format: int64 + example: en OntologyModifyDto: required: - prefix @@ -5511,8 +5532,9 @@ components: type: object properties: id: - type: integer - format: int64 + type: string + format: uuid + example: 7c491e40-082a-47b8-b82c-51d03c520466 uri: type: string example: 'http://www.wikidata.org/' @@ -5525,569 +5547,253 @@ components: rdf: type: boolean example: false - uri_pattern: - type: string - example: 'http://www.wikidata.org/entity/.*' - sparql_endpoint: - type: string - example: 'https://query.wikidata.org/sparql' - rdf_path: - type: string - example: rdf/om-2.0.rdf - BannerMessageUpdateDto: - required: - - message - - type - type: object - properties: - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: 'https://example.com' - link_text: - type: string - example: More - display_start: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - display_end: - type: string - format: date-time - example: '2021-03-12T15:26:21.000Z' - BannerMessageBriefDto: - required: - - message - - type - type: object - properties: - type: - type: string - enum: - - error - - warning - - info - message: - type: string - example: Maintenance starts on 8am on Monday - link: - type: string - example: 'https://example.com' - link_text: - type: string - example: More - ImageChangeDto: - required: - - dialect - - driver_class - - jdbc_method - - registry - type: object - properties: - registry: - type: string - example: docker.io/library - defaultPort: - maximum: 65535 - minimum: 1024 - type: integer - format: int32 - example: 5432 - dialect: - type: string - example: Postgres - driver_class: - type: string - example: org.postgresql.Driver - jdbc_method: - type: string - example: postgresql - DataTypeDto: - required: - - display_name - - documentation - - is_buildable - - is_quoted - - value - type: object - properties: - value: - type: string - example: time - documentation: - type: string - example: 'https://mariadb.com/kb/en/time/' - display_name: - type: string - example: TIME(fsp) - size_min: - type: integer - format: int32 - example: 0 - size_max: - type: integer - format: int32 - example: 6 - size_default: - type: integer - format: int32 - example: 0 - size_required: - type: boolean - example: false - d_min: - type: integer - format: int32 - d_max: - type: integer - format: int32 - d_default: - type: integer - format: int32 - d_required: - type: boolean - data_hint: - type: string - example: 'e.g. HH:MM:SS, HH:MM, HHMMSS, H:M:S' - type_hint: - type: string - example: 'fsp=microsecond precision, min. 0, max. 6' - is_quoted: - type: boolean - description: frontend needs to quote this data type - example: false - is_buildable: - type: boolean - description: frontend can build this data type - example: true - ImageDto: - required: - - data_types - - default - - default_port - - dialect - - driver_class - - id - - jdbc_method - - name - - operators - - registry - - version - type: object - properties: - id: - type: integer - format: int64 - example: 1 - registry: - type: string - example: docker.io/library - name: - type: string - example: mariadb - version: - type: string - example: '10.5' - dialect: - type: string - example: org.hibernate.dialect.MariaDBDialect - operators: - type: array - items: - $ref: '#/components/schemas/OperatorDto' - driver_class: - type: string - example: org.mariadb.jdbc.Driver - jdbc_method: - type: string - example: mariadb - default: - type: boolean - example: false - default_port: - type: integer - format: int32 - example: 3306 - data_types: - type: array - items: - $ref: '#/components/schemas/DataTypeDto' - OperatorDto: - required: - - display_name - - documentation - - value - type: object - properties: - id: - type: integer - format: int64 - value: + uri_pattern: type: string - example: XOR - documentation: + example: 'http://www.wikidata.org/entity/.*' + sparql_endpoint: type: string - example: 'https://mariadb.com/kb/en/xor/' - display_name: + example: 'https://query.wikidata.org/sparql' + rdf_path: type: string - example: XOR - IdentifierSaveDto: + example: rdf/om-2.0.rdf + BannerMessageUpdateDto: required: - - creators - - database_id - - id - - publication_year - - publisher - - titles + - message - type type: object properties: - id: - type: integer - format: int64 - example: 1 type: type: string - example: database enum: - - database - - subset - - table - - view - doi: + - error + - warning + - info + message: type: string - example: 10.1111/11111111 - titles: - type: array - items: - $ref: '#/components/schemas/SaveIdentifierTitleDto' - descriptions: - type: array - items: - $ref: '#/components/schemas/SaveIdentifierDescriptionDto' - funders: - type: array - items: - $ref: '#/components/schemas/SaveIdentifierFunderDto' - licenses: - type: array - items: - $ref: '#/components/schemas/LicenseDto' - publisher: + example: Maintenance starts on 8am on Monday + link: type: string - example: TU Wien - language: + example: 'https://example.com' + link_text: type: string - enum: - - ab - - aa - - af - - ak - - sq - - am - - ar - - an - - hy - - as - - av - - ae - - ay - - az - - bm - - ba - - eu - - be - - bn - - bh - - bi - - bs - - br - - bg - - my - - ca - - km - - ch - - ce - - ny - - zh - - cu - - cv - - kw - - co - - cr - - hr - - cs - - da - - dv - - nl - - dz - - en - - eo - - et - - ee - - fo - - fj - - fi - - fr - - ff - - gd - - gl - - lg - - ka - - de - - ki - - el - - kl - - gn - - gu - - ht - - ha - - he - - hz - - hi - - ho - - hu - - is - - io - - ig - - id - - ia - - ie - - iu - - ik - - ga - - it - - ja - - jv - - kn - - kr - - ks - - kk - - rw - - kv - - kg - - ko - - kj - - ku - - ky - - lo - - la - - lv - - lb - - li - - ln - - lt - - lu - - mk - - mg - - ms - - ml - - mt - - gv - - mi - - mr - - mh - - ro - - mn - - na - - nv - - nd - - ng - - ne - - se - - 'no' - - nb - - nn - - ii - - oc - - oj - - or - - om - - os - - pi - - pa - - ps - - fa - - pl - - pt - - qu - - rm - - rn - - ru - - sm - - sg - - sa - - sc - - sr - - sn - - sd - - si - - sk - - sl - - so - - st - - nr - - es - - su - - sw - - ss - - sv - - tl - - ty - - tg - - ta - - tt - - te - - th - - bo - - ti - - to - - ts - - tn - - tr - - tk - - tw - - ug - - uk - - ur - - uz - - ve - - vi - - vo - - wa - - cy - - fy - - wo - - xh - - yi - - yo - - za - - zu - creators: - type: array - items: - $ref: '#/components/schemas/SaveIdentifierCreatorDto' - database_id: + example: More + display_start: + type: string + format: date-time + example: '2021-03-12T15:26:21.000Z' + display_end: + type: string + format: date-time + example: '2021-03-12T15:26:21.000Z' + BannerMessageBriefDto: + required: + - message + - type + type: object + properties: + type: + type: string + enum: + - error + - warning + - info + message: + type: string + example: Maintenance starts on 8am on Monday + link: + type: string + example: 'https://example.com' + link_text: + type: string + example: More + ImageChangeDto: + required: + - dialect + - driver_class + - jdbc_method + - registry + type: object + properties: + registry: + type: string + example: docker.io/library + defaultPort: + maximum: 65535 + minimum: 1024 type: integer - format: int64 - example: 1 - query_id: + format: int32 + example: 5432 + dialect: + type: string + example: Postgres + driver_class: + type: string + example: org.postgresql.Driver + jdbc_method: + type: string + example: postgresql + DataTypeDto: + required: + - display_name + - documentation + - id + - is_buildable + - is_quoted + - value + type: object + properties: + id: + type: string + format: uuid + example: 816f55d5-1098-4f60-a4af-c8121c04dcca + value: + type: string + example: time + documentation: + type: string + example: 'https://mariadb.com/kb/en/time/' + display_name: + type: string + example: TIME(fsp) + size_min: type: integer - format: int64 - view_id: + format: int32 + example: 0 + size_max: type: integer - format: int64 - table_id: + format: int32 + example: 6 + size_default: type: integer - format: int64 - publication_day: + format: int32 + example: 0 + size_required: + type: boolean + example: false + d_min: type: integer format: int32 - example: 15 - publication_month: + d_max: type: integer format: int32 - example: 12 - publication_year: + d_default: type: integer format: int32 - example: 2022 - related_identifiers: - type: array - items: - $ref: '#/components/schemas/SaveRelatedIdentifierDto' - LicenseDto: + d_required: + type: boolean + data_hint: + type: string + example: 'e.g. HH:MM:SS, HH:MM, HHMMSS, H:M:S' + type_hint: + type: string + example: 'fsp=microsecond precision, min. 0, max. 6' + is_quoted: + type: boolean + description: frontend needs to quote this data type + example: false + is_buildable: + type: boolean + description: frontend can build this data type + example: true + ImageDto: required: - - identifier - - uri + - data_types + - default + - id + - name + - operators + - version type: object properties: - identifier: + id: type: string - example: MIT - uri: + format: uuid + example: 816f55d5-1098-4f60-a4af-c8121c04dcce + name: type: string - example: 'https://opensource.org/licenses/MIT' - description: + example: mariadb + version: type: string - example: >- - A short and simple permissive license with conditions only requiring - preservation of copyright and license notices. Licensed works, - modifications, and larger works may be distributed under different - terms and without source code. - SaveIdentifierCreatorDto: + example: '10.5' + operators: + type: array + items: + $ref: '#/components/schemas/OperatorDto' + default: + type: boolean + example: false + data_types: + type: array + items: + $ref: '#/components/schemas/DataTypeDto' + OperatorDto: required: - - creator_name + - display_name + - documentation - id + - value type: object properties: id: - type: integer - format: int64 - example: 1 - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Wesleyan University - creator_name: - type: string - example: 'Carberry, Josiah' - name_type: - type: string - example: Personal - enum: - - Personal - - Organizational - name_identifier: type: string - example: 0000-0002-1825-0097 - name_identifier_scheme: + format: uuid + example: 816f55d5-1098-4f60-a4af-c8121c04dccf + value: type: string - example: ORCID - enum: - - ORCID - - ROR - - ISNI - - GRID - affiliation_identifier: + example: XOR + documentation: type: string - example: 'https://ror.org/04d836q62' - affiliation_identifier_scheme: + example: 'https://mariadb.com/kb/en/xor/' + display_name: type: string - example: ROR - enum: - - ROR - - GRID - - ISNI - SaveIdentifierDescriptionDto: + example: XOR + IdentifierSaveDto: required: - - description + - creators + - database_id - id + - publication_year + - publisher + - titles + - type type: object properties: id: - type: integer - format: int64 - example: 1 - description: type: string - example: 'Air quality reports at Stephansplatz, Vienna' + format: uuid + example: 68e11675-1e0f-4d24-a6d9-887ad1c4445d + type: + type: string + example: database + enum: + - database + - subset + - table + - view + doi: + type: string + example: 10.1111/11111111 + titles: + type: array + items: + $ref: '#/components/schemas/SaveIdentifierTitleDto' + descriptions: + type: array + items: + $ref: '#/components/schemas/SaveIdentifierDescriptionDto' + funders: + type: array + items: + $ref: '#/components/schemas/SaveIdentifierFunderDto' + licenses: + type: array + items: + $ref: '#/components/schemas/LicenseDto' + publisher: + type: string + example: TU Wien language: type: string - example: en enum: - ab - aa @@ -6273,63 +5979,119 @@ components: - yo - za - zu - type: + creators: + type: array + items: + $ref: '#/components/schemas/SaveIdentifierCreatorDto' + database_id: type: string - example: Abstract - enum: - - Abstract - - Methods - - SeriesInformation - - TableOfContents - - TechnicalInfo - - Other - SaveIdentifierFunderDto: + format: uuid + query_id: + type: string + format: uuid + view_id: + type: string + format: uuid + table_id: + type: string + format: uuid + publication_day: + type: integer + format: int32 + example: 15 + publication_month: + type: integer + format: int32 + example: 12 + publication_year: + type: integer + format: int32 + example: 2022 + related_identifiers: + type: array + items: + $ref: '#/components/schemas/SaveRelatedIdentifierDto' + LicenseDto: required: - - funder_name + - identifier + - uri + type: object + properties: + identifier: + type: string + example: MIT + uri: + type: string + example: 'https://opensource.org/licenses/MIT' + description: + type: string + example: >- + A short and simple permissive license with conditions only requiring + preservation of copyright and license notices. Licensed works, + modifications, and larger works may be distributed under different + terms and without source code. + SaveIdentifierCreatorDto: + required: + - creator_name - id type: object properties: id: - type: integer - format: int64 - example: 1 - funder_name: type: string - example: European Commission - funder_identifier: + format: uuid + example: da9dd034-00a8-4517-b93d-d1b2adfee418 + firstname: type: string - example: 'http://doi.org/10.13039/501100000780' - funder_identifier_type: + example: Josiah + lastname: type: string - example: Crossref Funder ID + example: Carberry + affiliation: + type: string + example: Wesleyan University + creator_name: + type: string + example: 'Carberry, Josiah' + name_type: + type: string + example: Personal enum: - - Crossref Funder ID + - Personal + - Organizational + name_identifier: + type: string + example: 0000-0002-1825-0097 + name_identifier_scheme: + type: string + example: ORCID + enum: + - ORCID - ROR - - GND - ISNI - - Other - scheme_uri: - type: string - example: 'http://doi.org/' - award_number: + - GRID + affiliation_identifier: type: string - example: '824087' - award_title: + example: 'https://ror.org/04d836q62' + affiliation_identifier_scheme: type: string - example: EOSC-Life - SaveIdentifierTitleDto: + example: ROR + enum: + - ROR + - GRID + - ISNI + SaveIdentifierDescriptionDto: required: + - description - id - - title type: object properties: id: - type: integer - format: int64 - example: 1 - title: type: string - example: Airquality Demonstrator + format: uuid + example: 35bd84d8-b181-43c8-b786-4d024e4f843c + description: + type: string + example: 'Air quality reports at Stephansplatz, Vienna' language: type: string example: en @@ -6520,154 +6282,61 @@ components: - zu type: type: string - example: Subtitle + example: Abstract enum: - - AlternativeTitle - - Subtitle - - TranslatedTitle + - Abstract + - Methods + - SeriesInformation + - TableOfContents + - TechnicalInfo - Other - SaveRelatedIdentifierDto: - required: - - id - - relation - - type - - value - type: object - properties: - id: - type: integer - format: int64 - example: 1 - value: - type: string - example: 10.70124/dc4zh-9ce78 - type: - type: string - example: DOI - enum: - - DOI - - URL - - URN - - ARK - - arXiv - - bibcode - - EAN13 - - EISSN - - Handle - - IGSN - - ISBN - - ISTC - - LISSN - - LSID - - PMID - - PURL - - UPC - - w3id - relation: - type: string - example: Cites - enum: - - IsCitedBy - - Cites - - IsSupplementTo - - IsSupplementedBy - - IsContinuedBy - - Continues - - IsDescribedBy - - Describes - - HasMetadata - - IsMetadataFor - - HasVersion - - IsVersionOf - - IsNewVersionOf - - IsPreviousVersionOf - - IsPartOf - - HasPart - - IsPublishedIn - - IsReferencedBy - - References - - IsDocumentedBy - - Documents - - IsCompiledBy - - Compiles - - IsVariantFormOf - - IsOriginalFormOf - - IsIdenticalTo - - IsReviewedBy - - Reviews - - IsDerivedFrom - - IsSourceOf - - IsRequiredBy - - Requires - - IsObsoletedBy - - Obsoletes - CreatorDto: + SaveIdentifierFunderDto: required: - - creator_name + - funder_name - id type: object properties: id: - type: integer - format: int64 - example: 11 - firstname: - type: string - example: Josiah - lastname: - type: string - example: Carberry - affiliation: - type: string - example: Brown University - creator_name: - type: string - example: 'Carberry, Josiah' - name_type: - type: string - example: Personal - enum: - - Personal - - Organizational - name_identifier: - type: string - example: 0000-0002-1825-0097 - name_identifier_scheme: type: string - example: ORCID - enum: - - ORCID - - ROR - - ISNI - - GRID - name_identifier_scheme_uri: + format: uuid + example: 1c6b9212-a315-44b9-946c-3682a7a0e517 + funder_name: type: string - example: 'https://orcid.org/' - affiliation_identifier: + example: European Commission + funder_identifier: type: string - example: 'https://ror.org/05gq02987' - affiliation_identifier_scheme: + example: 'http://doi.org/10.13039/501100000780' + funder_identifier_type: type: string - example: ROR + example: Crossref Funder ID enum: + - Crossref Funder ID - ROR - - GRID + - GND - ISNI - affiliation_identifier_scheme_uri: + - Other + scheme_uri: type: string - example: 'https://ror.org/' - IdentifierDescriptionDto: + example: 'http://doi.org/' + award_number: + type: string + example: '824087' + award_title: + type: string + example: EOSC-Life + SaveIdentifierTitleDto: required: - id + - title type: object properties: id: - type: integer - format: int64 - example: 3 - description: type: string - example: 'Air quality reports at Stephansplatz, Vienna' + format: uuid + example: 2af9f40e-eaf5-4ea1-861a-1a696587bf29 + title: + type: string + example: Airquality Demonstrator language: type: string example: en @@ -6858,14 +6527,142 @@ components: - zu type: type: string - example: Abstract + example: Subtitle enum: - - Abstract - - Methods - - SeriesInformation - - TableOfContents - - TechnicalInfo + - AlternativeTitle + - Subtitle + - TranslatedTitle - Other + SaveRelatedIdentifierDto: + required: + - id + - relation + - type + - value + type: object + properties: + id: + type: string + format: uuid + example: 5bb272c7-7421-4f74-83ac-0486812d0f44 + value: + type: string + example: 10.70124/dc4zh-9ce78 + type: + type: string + example: DOI + enum: + - DOI + - URL + - URN + - ARK + - arXiv + - bibcode + - EAN13 + - EISSN + - Handle + - IGSN + - ISBN + - ISTC + - LISSN + - LSID + - PMID + - PURL + - UPC + - w3id + relation: + type: string + example: Cites + enum: + - IsCitedBy + - Cites + - IsSupplementTo + - IsSupplementedBy + - IsContinuedBy + - Continues + - IsDescribedBy + - Describes + - HasMetadata + - IsMetadataFor + - HasVersion + - IsVersionOf + - IsNewVersionOf + - IsPreviousVersionOf + - IsPartOf + - HasPart + - IsPublishedIn + - IsReferencedBy + - References + - IsDocumentedBy + - Documents + - IsCompiledBy + - Compiles + - IsVariantFormOf + - IsOriginalFormOf + - IsIdenticalTo + - IsReviewedBy + - Reviews + - IsDerivedFrom + - IsSourceOf + - IsRequiredBy + - Requires + - IsObsoletedBy + - Obsoletes + CreatorDto: + required: + - creator_name + - id + type: object + properties: + id: + type: string + format: uuid + example: e41f94a6-2b94-4a12-ac0e-678684e1c070 + firstname: + type: string + example: Josiah + lastname: + type: string + example: Carberry + affiliation: + type: string + example: Brown University + creator_name: + type: string + example: 'Carberry, Josiah' + name_type: + type: string + example: Personal + enum: + - Personal + - Organizational + name_identifier: + type: string + example: 0000-0002-1825-0097 + name_identifier_scheme: + type: string + example: ORCID + enum: + - ORCID + - ROR + - ISNI + - GRID + name_identifier_scheme_uri: + type: string + example: 'https://orcid.org/' + affiliation_identifier: + type: string + example: 'https://ror.org/05gq02987' + affiliation_identifier_scheme: + type: string + example: ROR + enum: + - ROR + - GRID + - ISNI + affiliation_identifier_scheme_uri: + type: string + example: 'https://ror.org/' IdentifierDto: required: - creators @@ -6887,9 +6684,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: b97cd56b-66ca-4354-9e6c-f47210cfaaec type: type: string example: database @@ -7129,21 +6926,17 @@ components: - draft - published database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid query_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid table_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid view_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid query_normalized: type: string example: >- @@ -7182,9 +6975,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: 39693413-e0ce-46da-ad5e-029c0556d439 funder_name: type: string example: European Commission @@ -7218,9 +7011,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 8 + type: string + format: uuid + example: ce9d11f0-60a2-448d-a3e4-44719a443e8a value: type: string example: 10.70124/dc4zh-9ce78 @@ -7319,9 +7112,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 4 + type: string + format: uuid + example: 787439d0-e85e-400c-a7e6-996a023bfad9 name: type: string example: Air Quality @@ -7329,9 +7122,9 @@ components: type: string example: SELECT `id` FROM `air_quality` ORDER BY `value` DESC database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: 2b5b2b03-fdd0-40d6-afe0-e5d02fd839e4 internal_name: type: string example: air_quality @@ -7382,9 +7175,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 3 + type: string + format: uuid + example: 41ed10e0-687b-4e18-8521-810f5cffbce1 name: type: string example: Air Quality @@ -7392,9 +7185,9 @@ components: type: string example: Air Quality in Austria database_id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: a8fec026-dfaf-4b1d-8f6c-f01720d91705 internal_name: type: string example: air_quality @@ -7431,9 +7224,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: a453e444-e00d-41ca-902c-11e9c54b39f1 name: maxLength: 64 minLength: 0 @@ -7467,26 +7260,20 @@ components: example: Column comment enums: type: array - example: - - val1 items: - type: string - example: '["val1"]' + $ref: '#/components/schemas/EnumDto' sets: type: array - example: - - val1 items: - type: string - example: '["val1"]' + $ref: '#/components/schemas/SetDto' database_id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: 911f9052-c58c-4e1c-b3f2-66af2107be16 table_id: - type: integer - format: int64 - example: 3 + type: string + format: uuid + example: bfffa915-a547-4466-9c65-ddc0d38fdb08 ord: type: integer format: int32 @@ -7569,9 +7356,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 23 + type: string + format: uuid + example: 8cabc011-4bdf-44d4-9d33-b2648e2ddbf1 uri: type: string example: 'http://www.wikidata.org/entity/Q202444' @@ -7580,9 +7367,35 @@ components: example: given name description: type: string - example: >- - name typically used to differentiate people from the same family, - clan, or other social group who have a common last name + example: >- + name typically used to differentiate people from the same family, + clan, or other social group who have a common last name + EnumDto: + required: + - id + - value + type: object + properties: + id: + type: string + format: uuid + example: 5343bb3d-14d3-4eb7-a86f-b8fc553cb315 + value: + type: string + example: '3' + SetDto: + required: + - id + - value + type: object + properties: + id: + type: string + format: uuid + example: 7eb4eded-bacc-4a91-84db-a9ae6ddafda7 + value: + type: string + example: '3' UnitBriefDto: required: - id @@ -7590,9 +7403,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 34 + type: string + format: uuid + example: ba1935e8-6817-488f-af0a-f54389af9000 uri: type: string example: 'http://www.wikidata.org/entity/Q1422583' @@ -7627,33 +7440,6 @@ components: - read - write_own - write_all - CreateUserDto: - required: - - email - - password - - username - type: object - properties: - username: - pattern: '^[a-z0-9]{3,}$' - type: string - example: user - email: - type: string - example: user@example.com - password: - type: string - LoginRequestDto: - required: - - password - - username - type: object - properties: - username: - type: string - example: user - password: - type: string OntologyCreateDto: required: - prefix @@ -7964,18 +7750,18 @@ components: items: $ref: '#/components/schemas/SaveIdentifierCreatorDto' database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: d002e8d5-8db4-4ff7-ab3a-bc3f52d9ec44 query_id: - type: integer - format: int64 + type: string + format: uuid view_id: - type: integer - format: int64 + type: string + format: uuid table_id: - type: integer - format: int64 + type: string + format: uuid publication_day: type: integer format: int32 @@ -8004,9 +7790,9 @@ components: type: string example: Air Quality container_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: 0888e108-d521-46e2-9d3e-82099185305b is_public: type: boolean example: true @@ -8027,8 +7813,7 @@ components: type: string example: Air Quality query: - type: string - example: SELECT `id` FROM `air_quality` + $ref: '#/components/schemas/SubsetDto' is_public: type: boolean example: true @@ -8044,16 +7829,24 @@ components: properties: columns: type: array + example: + - id items: type: string + example: '["id"]' referenced_table: type: string + example: sensor referenced_columns: type: array + example: + - other_id items: type: string + example: '["other_id"]' on_update: type: string + example: cascade enum: - restrict - cascade @@ -8062,6 +7855,7 @@ components: - set_default on_delete: type: string + example: cascade enum: - restrict - cascade @@ -8080,7 +7874,7 @@ components: example: Date type: type: string - example: string + example: varchar enum: - char - varchar @@ -8233,10 +8027,10 @@ components: format: int64 example: 50 image_id: - type: integer + type: string description: Image ID - format: int64 - example: 1 + format: uuid + example: 2360f3c4-85e0-4fac-a7c6-73b296b9dde2 ui_host: type: string example: example.com @@ -8259,23 +8053,15 @@ components: - image - internal_name - name - - quota type: object properties: id: - type: integer - format: int64 - example: 4 + type: string + format: uuid + example: 7ddb7e87-b965-43a2-9a24-4fa406d998f4 name: type: string example: Air Quality - host: - type: string - example: data-db - port: - type: integer - format: int32 - example: 3306 image: $ref: '#/components/schemas/ImageDto' quota: @@ -8298,13 +8084,6 @@ components: internal_name: type: string example: air_quality - ui_host: - type: string - example: example.com - ui_port: - type: integer - format: int32 - example: 3306 ColumnBriefDto: required: - database_id @@ -8316,9 +8095,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: a453e444-e00d-41ca-902c-11e9c54b39f1 name: maxLength: 64 minLength: 0 @@ -8328,13 +8107,13 @@ components: type: string example: firstname database_id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: 911f9052-c58c-4e1c-b3f2-66af2107be16 table_id: - type: integer - format: int64 - example: 3 + type: string + format: uuid + example: bfffa915-a547-4466-9c65-ddc0d38fdb08 internal_name: maxLength: 64 minLength: 0 @@ -8382,8 +8161,9 @@ components: type: object properties: id: - type: integer - format: int64 + type: string + format: uuid + example: ba1935e8-6817-488f-af0a-f54389af9000 uri: type: string name: @@ -8404,8 +8184,9 @@ components: type: object properties: id: - type: integer - format: int64 + type: string + format: uuid + example: 7c491e40-082a-47b8-b82c-51d03c520466 uri: type: string example: 'http://www.wikidata.org/' @@ -8465,10 +8246,12 @@ components: type: object properties: id: - type: integer - format: int64 + type: string + format: uuid + example: ae3f795b-a3da-4ebe-bdc4-21a8ce631e6f type: type: string + example: WARNING enum: - error - warning @@ -8494,24 +8277,20 @@ components: required: - default - id - - jdbc_method - name - version type: object properties: id: - type: integer - format: int64 - example: 5 + type: string + format: uuid + example: 816f55d5-1098-4f60-a4af-c8121c04dcce name: type: string example: mariadb version: type: string example: '10.5' - jdbc_method: - type: string - example: mariadb default: type: boolean example: false @@ -8577,6 +8356,153 @@ components: type: string '@type': type: string + ViewColumnDto: + required: + - database_id + - id + - internal_name + - is_null_allowed + - name + - ord + - type + type: object + properties: + id: + type: string + format: uuid + example: 6aec3a91-2e0b-4e92-a16a-9c3c5e892da1 + name: + maxLength: 64 + minLength: 0 + type: string + example: Given Name + size: + type: integer + format: int64 + example: 255 + d: + type: integer + format: int64 + example: 0 + description: + maxLength: 2048 + minLength: 0 + type: string + example: Column comment + database_id: + type: string + format: uuid + example: 2b5b2b03-fdd0-40d6-afe0-e5d02fd839e4 + ord: + type: integer + format: int32 + example: 0 + internal_name: + maxLength: 64 + minLength: 0 + type: string + example: given_name + index_length: + type: integer + format: int64 + example: 255 + length: + type: integer + format: int64 + example: 255 + type: + type: string + example: varchar + enum: + - char + - varchar + - binary + - varbinary + - tinyblob + - tinytext + - text + - blob + - mediumtext + - mediumblob + - longtext + - longblob + - enum + - set + - serial + - bit + - tinyint + - bool + - smallint + - mediumint + - int + - bigint + - float + - double + - decimal + - date + - datetime + - timestamp + - time + - year + is_null_allowed: + type: boolean + example: false + ViewDto: + required: + - columns + - database_id + - id + - identifiers + - internal_name + - name + - owner + - query + - query_hash + type: object + properties: + id: + type: string + format: uuid + example: 787439d0-e85e-400c-a7e6-996a023bfad9 + name: + type: string + example: Air Quality + identifiers: + type: array + items: + $ref: '#/components/schemas/IdentifierDto' + query: + type: string + example: SELECT `id` FROM `air_quality` ORDER BY `value` DESC + owner: + $ref: '#/components/schemas/UserBriefDto' + columns: + type: array + items: + $ref: '#/components/schemas/ViewColumnDto' + last_retrieved: + type: string + format: date-time + database_id: + type: string + format: uuid + example: fc29f89c-86a8-4020-9e36-4d954736c6cc + internal_name: + type: string + example: air_quality + is_public: + type: boolean + example: true + is_schema_public: + type: boolean + example: true + initial_view: + type: boolean + description: True if it is the default view for the database + example: true + query_hash: + type: string + example: 7de03e818900b6ea6d58ad0306d4a741d658c6df3d1964e89ed2395d8c7e7916 ConstraintsDto: type: object properties: @@ -8601,86 +8527,13 @@ components: type: array items: $ref: '#/components/schemas/PrimaryKeyDto' - DatabaseDto: - required: - - accesses - - contact - - exchange_name - - id - - identifiers - - internal_name - - is_public - - is_schema_public - - name - - owner - - subsets - - tables - - views - type: object - properties: - id: - type: integer - format: int64 - example: 3 - name: - type: string - example: Air Quality - description: - type: string - example: Air Quality - tables: - type: array - items: - $ref: '#/components/schemas/TableDto' - views: - type: array - items: - $ref: '#/components/schemas/ViewDto' - container: - $ref: '#/components/schemas/ContainerDto' - accesses: - type: array - items: - $ref: '#/components/schemas/DatabaseAccessDto' - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - subsets: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - contact: - $ref: '#/components/schemas/UserBriefDto' - owner: - $ref: '#/components/schemas/UserBriefDto' - last_retrieved: - type: string - format: date-time - exchange_name: - type: string - example: dbrepo - exchange_type: - type: string - example: topic - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - is_schema_public: - type: boolean - example: true - preview_image: - type: string ForeignKeyBriefDto: type: object properties: id: - type: integer - format: int64 - example: 8 + type: string + format: uuid + example: f2b740ec-0b13-4d07-88a9-529d354bba6a ForeignKeyDto: required: - name @@ -8690,9 +8543,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 4 + type: string + format: uuid + example: f2b740ec-0b13-4d07-88a9-529d354bba6a name: type: string example: fk_name @@ -8730,9 +8583,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 8 + type: string + format: uuid + example: f2b740ec-0b13-4d07-88a9-529d354bba6a column: $ref: '#/components/schemas/ColumnBriefDto' foreign_key: @@ -8746,9 +8599,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 8 + type: string + format: uuid + example: d984f9d7-e8a7-4b81-b59a-862db1871f18 table: $ref: '#/components/schemas/TableBriefDto' column: @@ -8770,9 +8623,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 3 + type: string + format: uuid + example: d346f844-b84c-490f-9aec-725a2dc8f820 name: type: string example: Air Quality @@ -8794,17 +8647,15 @@ components: type: array items: $ref: '#/components/schemas/ColumnDto' - database: - $ref: '#/components/schemas/DatabaseDto' constraints: $ref: '#/components/schemas/ConstraintsDto' last_retrieved: type: string format: date-time database_id: - type: integer - format: int64 - example: 2 + type: string + format: uuid + example: fc29f89c-86a8-4020-9e36-4d954736c6cc internal_name: type: string example: air_quality @@ -8854,9 +8705,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 5 + type: string + format: uuid + example: d984f9d7-e8a7-4b81-b59a-862db1871f13 name: type: string example: uk_name @@ -8866,155 +8717,6 @@ components: type: array items: $ref: '#/components/schemas/ColumnBriefDto' - ViewColumnDto: - required: - - database_id - - id - - internal_name - - is_null_allowed - - name - - ord - - type - type: object - properties: - id: - type: integer - format: int64 - example: 12 - name: - maxLength: 64 - minLength: 0 - type: string - example: Given Name - size: - type: integer - format: int64 - example: 255 - d: - type: integer - format: int64 - example: 0 - description: - maxLength: 2048 - minLength: 0 - type: string - example: Column comment - database_id: - type: integer - format: int64 - example: 1 - ord: - type: integer - format: int32 - example: 0 - internal_name: - maxLength: 64 - minLength: 0 - type: string - example: given_name - index_length: - type: integer - format: int64 - example: 255 - length: - type: integer - format: int64 - example: 255 - type: - type: string - example: varchar - enum: - - char - - varchar - - binary - - varbinary - - tinyblob - - tinytext - - text - - blob - - mediumtext - - mediumblob - - longtext - - longblob - - enum - - set - - serial - - bit - - tinyint - - bool - - smallint - - mediumint - - int - - bigint - - float - - double - - decimal - - date - - datetime - - timestamp - - time - - year - is_null_allowed: - type: boolean - example: false - ViewDto: - required: - - columns - - database_id - - id - - identifiers - - internal_name - - name - - owner - - query - - query_hash - type: object - properties: - id: - type: integer - format: int64 - example: 4 - name: - type: string - example: Air Quality - identifiers: - type: array - items: - $ref: '#/components/schemas/IdentifierDto' - query: - type: string - example: SELECT `id` FROM `air_quality` ORDER BY `value` DESC - database: - $ref: '#/components/schemas/DatabaseDto' - owner: - $ref: '#/components/schemas/UserBriefDto' - columns: - type: array - items: - $ref: '#/components/schemas/ViewColumnDto' - last_retrieved: - type: string - format: date-time - database_id: - type: integer - format: int64 - example: 1 - internal_name: - type: string - example: air_quality - is_public: - type: boolean - example: true - is_schema_public: - type: boolean - example: true - initial_view: - type: boolean - description: True if it is the default view for the database - example: true - query_hash: - type: string - example: 7de03e818900b6ea6d58ad0306d4a741d658c6df3d1964e89ed2395d8c7e7916 TableColumnEntityDto: required: - column_id @@ -9033,17 +8735,17 @@ components: type: string example: open source semantic web framework for Java database_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: 475b4107-a64d-4495-a7ef-3cb0dadd4804 table_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: 9a9208af-90ea-4382-9a11-0c8f6d89bd1f column_id: - type: integer - format: int64 - example: 1 + type: string + format: uuid + example: 297860e3-3b29-451c-ae8a-a85ed5941018 ContainerBriefDto: required: - count @@ -9056,9 +8758,9 @@ components: type: object properties: id: - type: integer - format: int64 - example: 4 + type: string + format: uuid + example: 7ddb7e87-b965-43a2-9a24-4fa406d998f4 hash: type: string example: f829dd8a884182d0da846f365dee1221fd16610a14c81b8f9f295ff162749e50 @@ -9086,8 +8788,9 @@ components: type: object properties: id: - type: integer - format: int64 + type: string + format: uuid + example: 8cabc011-4bdf-44d4-9d33-b2648e2ddbf1 uri: type: string name: diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java index 2e0c154e03..3fe8744661 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/FilterDto.java @@ -29,7 +29,7 @@ public class FilterDto { @NotNull @JsonProperty("operator_id") - @Schema(example = ">") + @Schema(example = "67c5b54d-2eb0-4f42-8dc1-a504562e9f32") private UUID operatorId; @NotNull diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java index 7a14b50c20..bb58ad4831 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/query/OrderDto.java @@ -23,7 +23,7 @@ public class OrderDto { @Schema(example = "e891ba86-0258-41a6-a8d9-ff58bc10b618") private UUID columnId; - @Schema(example = "ASC") + @Schema(example = "asc") private OrderTypeDto direction; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/CreateTableColumnDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/CreateTableColumnDto.java index ca7f3b8d58..9733f64a16 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/CreateTableColumnDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/CreateTableColumnDto.java @@ -28,7 +28,7 @@ public class CreateTableColumnDto { private Long indexLength; @NotNull - @Schema(example = "string") + @Schema(example = "varchar") private ColumnTypeDto type; @Schema(example = "255") diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/EnumDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/EnumDto.java index 1922dc308b..9038648513 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/EnumDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/EnumDto.java @@ -18,7 +18,7 @@ import java.util.UUID; public class EnumDto { @NotNull - @Schema(example = "1") + @Schema(example = "5343bb3d-14d3-4eb7-a86f-b8fc553cb315") private UUID id; @NotNull diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/SetDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/SetDto.java index 763968e8f5..6986212592 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/SetDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/columns/SetDto.java @@ -18,7 +18,7 @@ import java.util.UUID; public class SetDto { @NotNull - @Schema(example = "1") + @Schema(example = "7eb4eded-bacc-4a91-84db-a9ae6ddafda7") private UUID id; @NotNull diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/CreateForeignKeyDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/CreateForeignKeyDto.java index 31e43b0c6a..5e1d0a9f86 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/CreateForeignKeyDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/constraints/foreign/CreateForeignKeyDto.java @@ -1,6 +1,7 @@ package at.tuwien.api.database.table.constraints.foreign; import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.extern.jackson.Jacksonized; @@ -17,19 +18,24 @@ import java.util.List; public class CreateForeignKeyDto { @NotNull + @Schema(example = "[\"id\"]") private List<String> columns; @NotNull + @Schema(example = "sensor") @JsonProperty("referenced_table") private String referencedTable; @NotNull + @Schema(example = "[\"other_id\"]") @JsonProperty("referenced_columns") private List<String> referencedColumns; + @Schema(example = "cascade") @JsonProperty("on_update") private ReferenceTypeDto onUpdate; + @Schema(example = "cascade") @JsonProperty("on_delete") private ReferenceTypeDto onDelete; } diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierBriefDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierBriefDto.java index 43e32b8ae0..0434d1b21f 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierBriefDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/identifier/IdentifierBriefDto.java @@ -25,7 +25,7 @@ public class IdentifierBriefDto { @NotNull @JsonProperty("database_id") - @Schema(example = "1") + @Schema(example = "fc29f89c-86a8-4020-9e36-4d954736c6cc") private UUID databaseId; @JsonProperty("query_id") diff --git a/lib/python/dbrepo/api/dto.py b/lib/python/dbrepo/api/dto.py index 59c8210c76..fd378739cf 100644 --- a/lib/python/dbrepo/api/dto.py +++ b/lib/python/dbrepo/api/dto.py @@ -1038,8 +1038,8 @@ class Column(BaseModel): median: Optional[float] = None concept: Optional[ConceptBrief] = None unit: Optional[UnitBrief] = None - enums: Optional[List[str]] = field(default_factory=list) - sets: Optional[List[str]] = field(default_factory=list) + enums: Optional[List[ColumnEnum]] = field(default_factory=list) + sets: Optional[List[ColumnSet]] = field(default_factory=list) index_length: Optional[int] = None length: Optional[int] = None data_length: Optional[int] = None diff --git a/lib/python/tests/test_dtos.py b/lib/python/tests/test_dtos.py index 3f05e24081..3e99135e8b 100644 --- a/lib/python/tests/test_dtos.py +++ b/lib/python/tests/test_dtos.py @@ -35,9 +35,10 @@ dictConfig({ }) -class AnalyseUnitTest(unittest.TestCase): +class DtoUnitTest(unittest.TestCase): schemas = None models: [()] = [] + exclusions: [str] = ['EnumType'] found: int = 0 skipped: [str] = [] @@ -48,7 +49,7 @@ class AnalyseUnitTest(unittest.TestCase): self.found += 1 if not inspect.isclass(obj): continue - if f'{name}Dto' not in self.schemas: + if f'{name}Dto' not in self.schemas or name not in self.exclusions: logging.debug(f'skip model {name}: OpenAPI schema definition {name}Dto not found') self.skipped.append(f'{name}Dto') continue -- GitLab From 503f9ad245b90333699c415dfead4270b962f809 Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Sun, 2 Mar 2025 15:50:10 +0100 Subject: [PATCH 08/11] Fixed tests Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- .../tuwien/handlers/ApiExceptionHandler.java | 7 +++ .../endpoints/DatabaseEndpointUnitTest.java | 26 ++++----- .../endpoints/ViewEndpointUnitTest.java | 54 ++++++++----------- ...nticationPrivilegedIntegrationMvcTest.java | 24 --------- .../main/java/at/tuwien/test/BaseTest.java | 5 ++ 5 files changed, 45 insertions(+), 71 deletions(-) diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java index aca2f9f356..eadce489d9 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java @@ -473,6 +473,13 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.CONFLICT) + @ExceptionHandler(ViewExistsException.class) + public ResponseEntity<ApiErrorDto> handle(ViewExistsException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.BAD_REQUEST) @ExceptionHandler(ViewMalformedException.class) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java index 9978574d15..28117400a6 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java @@ -563,8 +563,8 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void findById_anonymousPublicSchemaNoAccess_succeeds() throws UserNotFoundException, NotAllowedException, - DataServiceException, DatabaseNotFoundException, ExchangeNotFoundException, DataServiceConnectionException { + public void findById_anonymousPublicSchemaNoAccess_succeeds() throws NotAllowedException, + DatabaseNotFoundException { /* test */ final DatabaseDto database = findById_generic(DATABASE_2_ID, DATABASE_2, null); @@ -575,13 +575,12 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_LOCAL_ADMIN_USERNAME, authorities = {"system"}) - public void findById_privateSchemaNoAccessInternalUser_succeeds() throws UserNotFoundException, - NotAllowedException, DataServiceException, DatabaseNotFoundException, ExchangeNotFoundException, - DataServiceConnectionException { + public void findById_privateSchemaNoAccessInternalUser_succeeds() throws NotAllowedException, + DatabaseNotFoundException { /* test */ final DatabaseDto database = findById_generic(DATABASE_3_ID, DATABASE_3, USER_LOCAL_ADMIN_PRINCIPAL); - assertEquals(0, database.getTables().size()); + assertEquals(1, database.getTables().size()); assertEquals(1, database.getViews().size()); assertNotEquals(0, database.getAccesses().size()); } @@ -608,8 +607,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME) - public void findById_ownerSeesAccessRights_succeeds() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, NotAllowedException { + public void findById_ownerSeesAccessRights_succeeds() throws DatabaseNotFoundException, NotAllowedException { /* mock */ when(accessService.list(DATABASE_1)) @@ -624,8 +622,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_2_USERNAME) - public void findById_hiddenAccessRights_succeeds() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, NotAllowedException { + public void findById_hiddenAccessRights_succeeds() throws DatabaseNotFoundException, NotAllowedException { /* mock */ when(accessService.list(DATABASE_1)) @@ -640,8 +637,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME) - public void findById_hiddenAccessRightsSeesOwn_succeeds() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, NotAllowedException { + public void findById_hiddenAccessRightsSeesOwn_succeeds() throws DatabaseNotFoundException, NotAllowedException { /* mock */ when(accessService.list(DATABASE_1)) @@ -775,8 +771,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } public DatabaseDto findById_generic(UUID databaseId, Database database, Principal principal) - throws DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException, - DataServiceException, UserNotFoundException, NotAllowedException { + throws DatabaseNotFoundException, NotAllowedException { /* mock */ if (database != null) { @@ -796,7 +791,8 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { return body; } - public ResponseEntity<byte[]> findPreviewImage_generic(UUID databaseId, Database database) throws DatabaseNotFoundException { + public ResponseEntity<byte[]> findPreviewImage_generic(UUID databaseId, Database database) + throws DatabaseNotFoundException { /* mock */ if (database != null) { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java index a1c4dabbc8..ac5a8ef524 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java @@ -103,7 +103,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(AccessDeniedException.class, () -> { - create_generic(DATABASE_3_ID, DATABASE_3, null, null, null, null); + create_generic(DATABASE_3_ID, DATABASE_3, "View", null, null, null, null); }); } @@ -113,7 +113,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - create_generic(DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL, USER_2_ID, USER_2, null); + create_generic(DATABASE_3_ID, DATABASE_3, "View", USER_2_PRINCIPAL, USER_2_ID, USER_2, null); }); } @@ -123,7 +123,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - create_generic(DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + create_generic(DATABASE_3_ID, DATABASE_3, "View", USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); }); } @@ -133,7 +133,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(AccessDeniedException.class, () -> { - create_generic(DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL, USER_2_ID, USER_2, null); + create_generic(DATABASE_3_ID, DATABASE_3, "View", USER_2_PRINCIPAL, USER_2_ID, USER_2, null); }); } @@ -145,7 +145,17 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { ImageNotFoundException, ViewExistsException { /* test */ - create_generic(DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL, USER_1_ID, USER_1, DATABASE_1_USER_1_WRITE_ALL_ACCESS); + create_generic(DATABASE_1_ID, DATABASE_1, "View", USER_1_PRINCIPAL, USER_1_ID, USER_1, DATABASE_1_USER_1_WRITE_ALL_ACCESS); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-database-view"}) + public void create_exists_fails() { + + /* test */ + assertThrows(ViewExistsException.class, () -> { + create_generic(DATABASE_1_ID, DATABASE_1, VIEW_1_NAME, USER_1_PRINCIPAL, USER_1_ID, USER_1, DATABASE_1_USER_1_WRITE_ALL_ACCESS); + }); } @Test @@ -175,26 +185,6 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { find_generic(DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); } - @Test - @WithMockUser(username = USER_2_USERNAME) - public void find_publicSystem_succeeds() throws UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, ViewNotFoundException { - - /* test */ - final ResponseEntity<ViewDto> response = find_generic(DATABASE_3_ID, DATABASE_3, USER_LOCAL_ADMIN_PRINCIPAL, - USER_LOCAL_ADMIN_ID, null, null); - final HttpHeaders headers = response.getHeaders(); - assertEquals(List.of(CONTAINER_1_PRIVILEGED_USERNAME), headers.get("X-Username")); - assertEquals(List.of(CONTAINER_1_PRIVILEGED_PASSWORD), headers.get("X-Password")); - assertEquals(List.of(CONTAINER_1_HOST), headers.get("X-Host")); - assertEquals(List.of("" + CONTAINER_1_PORT), headers.get("X-Port")); - assertEquals(List.of(IMAGE_1_JDBC), headers.get("X-Type")); - assertEquals(List.of(DATABASE_3_INTERNALNAME), headers.get("X-Database")); - assertEquals(List.of(VIEW_5_INTERNAL_NAME), headers.get("X-View")); - assertEquals(List.of(IMAGE_1_JDBC), headers.get("X-Jdbc-Method")); - assertEquals(List.of("X-Username X-Password X-Host X-Port X-Type X-Database X-View X-Jdbc-Method"), headers.get("Access-Control-Expose-Headers")); - } - @Test @WithMockUser(username = USER_2_USERNAME) public void find_publicHasRoleHasAccess_succeeds() throws UserNotFoundException, DatabaseNotFoundException, @@ -290,7 +280,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(AccessDeniedException.class, () -> { - create_generic(DATABASE_1_ID, DATABASE_1, null, null, null, null); + create_generic(DATABASE_1_ID, DATABASE_1, "View", null, null, null, null); }); } @@ -300,7 +290,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - create_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, null); + create_generic(DATABASE_1_ID, DATABASE_1, "View", USER_2_PRINCIPAL, USER_2_ID, USER_2, null); }); } @@ -310,7 +300,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - create_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); + create_generic(DATABASE_1_ID, DATABASE_1, "View", USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); }); } @@ -320,7 +310,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(AccessDeniedException.class, () -> { - create_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, null); + create_generic(DATABASE_1_ID, DATABASE_1, "View", USER_2_PRINCIPAL, USER_2_ID, USER_2, null); }); } @@ -479,13 +469,13 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { } } - protected void create_generic(UUID databaseId, Database database, Principal principal, UUID userId, User user, - DatabaseAccess access) throws MalformedException, DataServiceException, + protected void create_generic(UUID databaseId, Database database, String viewName, Principal principal, UUID userId, + User user, DatabaseAccess access) throws MalformedException, DataServiceException, DataServiceConnectionException, NotAllowedException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, TableNotFoundException, ImageNotFoundException, ViewExistsException { final CreateViewDto request = CreateViewDto.builder() - .name(VIEW_1_NAME) + .name(viewName) .query(VIEW_1_SUBSET_DTO) .isPublic(VIEW_1_PUBLIC) .build(); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java index e47229bd0a..91194375d0 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/AuthenticationPrivilegedIntegrationMvcTest.java @@ -100,10 +100,6 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest /* test */ this.mockMvc.perform(get("/api/database/" + DATABASE_1_ID).with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) .andDo(print()) - .andExpect(header().doesNotExist("X-Username")) - .andExpect(header().doesNotExist("X-Password")) - .andExpect(header().doesNotExist("X-Jdbc-Method")) - .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) .andExpect(status().isOk()); } @@ -151,10 +147,6 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest /* test */ this.mockMvc.perform(get("/api/database/" + DATABASE_1_ID + "/table/" + TABLE_1_ID).header("Authorization", "Bearer " + jwt.getAccessToken())) .andDo(print()) - .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) - .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) - .andExpect(header().string("X-Jdbc-Method", IMAGE_1_JDBC)) - .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Jdbc-Method")) .andExpect(status().isOk()); } @@ -167,10 +159,6 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest /* test */ this.mockMvc.perform(get("/api/database/" + DATABASE_1_ID + "/table/" + TABLE_1_ID).with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) .andDo(print()) - .andExpect(header().doesNotExist("X-Username")) - .andExpect(header().doesNotExist("X-Password")) - .andExpect(header().doesNotExist("X-Jdbc-Method")) - .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) .andExpect(status().isOk()); } @@ -183,10 +171,6 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest /* test */ this.mockMvc.perform(get("/api/database/" + DATABASE_1_ID + "/table/" + TABLE_1_ID).with(httpBasic(USER_LOCAL_ADMIN_USERNAME, USER_LOCAL_ADMIN_PASSWORD))) .andDo(print()) - .andExpect(header().string("X-Username", CONTAINER_1_PRIVILEGED_USERNAME)) - .andExpect(header().string("X-Password", CONTAINER_1_PRIVILEGED_PASSWORD)) - .andExpect(header().string("X-Jdbc-Method", IMAGE_1_JDBC)) - .andExpect(header().string("Access-Control-Expose-Headers", "X-Username X-Password X-Jdbc-Method")) .andExpect(status().isOk()); } @@ -200,10 +184,6 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest /* test */ this.mockMvc.perform(get("/api/database/" + DATABASE_1_ID + "/view/" + VIEW_1_ID).with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) .andDo(print()) - .andExpect(header().doesNotExist("X-Username")) - .andExpect(header().doesNotExist("X-Password")) - .andExpect(header().doesNotExist("X-Jdbc-Method")) - .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) .andExpect(status().isOk()); } @@ -216,10 +196,6 @@ public class AuthenticationPrivilegedIntegrationMvcTest extends AbstractUnitTest /* test */ this.mockMvc.perform(get("/api/container/" + CONTAINER_1_ID).with(httpBasic(USER_1_USERNAME, USER_1_PASSWORD))) .andDo(print()) - .andExpect(header().doesNotExist("X-Username")) - .andExpect(header().doesNotExist("X-Password")) - .andExpect(header().doesNotExist("X-Jdbc-Method")) - .andExpect(header().doesNotExist("Access-Control-Expose-Headers")) .andExpect(status().isOk()); } diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java index c39cafae31..53880e19b6 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java @@ -5007,6 +5007,7 @@ public abstract class BaseTest { public static final ViewDto VIEW_1_DTO = ViewDto.builder() .id(VIEW_1_ID) + .databaseId(DATABASE_1_ID) .isInitialView(VIEW_1_INITIAL_VIEW) .name(VIEW_1_NAME) .internalName(VIEW_1_INTERNAL_NAME) @@ -5160,6 +5161,7 @@ public abstract class BaseTest { public static final ViewDto VIEW_2_DTO = ViewDto.builder() .id(VIEW_2_ID) + .databaseId(DATABASE_1_ID) .isInitialView(VIEW_2_INITIAL_VIEW) .name(VIEW_2_NAME) .internalName(VIEW_2_INTERNAL_NAME) @@ -5308,6 +5310,7 @@ public abstract class BaseTest { public static final ViewDto VIEW_3_DTO = ViewDto.builder() .id(VIEW_3_ID) + .databaseId(DATABASE_1_ID) .isInitialView(VIEW_3_INITIAL_VIEW) .name(VIEW_3_NAME) .internalName(VIEW_3_INTERNAL_NAME) @@ -5513,6 +5516,7 @@ public abstract class BaseTest { public static final ViewDto VIEW_4_DTO = ViewDto.builder() .id(VIEW_4_ID) + .databaseId(DATABASE_2_ID) .isInitialView(VIEW_4_INITIAL_VIEW) .name(VIEW_4_NAME) .internalName(VIEW_4_INTERNAL_NAME) @@ -5717,6 +5721,7 @@ public abstract class BaseTest { public static final ViewDto VIEW_5_DTO = ViewDto.builder() .id(VIEW_5_ID) + .databaseId(DATABASE_3_ID) .isInitialView(VIEW_5_INITIAL_VIEW) .name(VIEW_5_NAME) .internalName(VIEW_5_INTERNAL_NAME) -- GitLab From 1ac60a563b3389d069e8e4e5376a766d2510a384 Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Sun, 2 Mar 2025 16:58:07 +0100 Subject: [PATCH 09/11] Updated tests Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- dbrepo-analyse-service/Pipfile.lock | 76 +++++++------- .../lib/dbrepo-1.7.0-py3-none-any.whl | Bin 31116 -> 31084 bytes .../lib/dbrepo-1.7.0.tar.gz | Bin 46110 -> 48573 bytes .../at/tuwien/endpoints/TableEndpoint.java | 2 +- .../tuwien/handlers/ApiExceptionHandler.java | 7 ++ .../java/at/tuwien/config/MariaDbConfig.java | 6 +- .../endpoint/TableEndpointUnitTest.java | 94 +++++++++++------- .../MetadataServiceGatewayUnitTest.java | 21 ---- .../DefaultListenerIntegrationTest.java | 2 +- .../listener/DefaultListenerUnitTest.java | 4 +- .../service/AccessServiceIntegrationTest.java | 2 +- .../DatabaseServiceIntegrationTest.java | 4 +- .../service/QueueServiceIntegrationTest.java | 9 +- .../service/SubsetServiceIntegrationTest.java | 11 +- .../service/TableServiceIntegrationTest.java | 4 +- .../service/ViewServiceIntegrationTest.java | 2 +- .../main/java/at/tuwien/test/BaseTest.java | 3 +- dbrepo-search-service/Pipfile.lock | 82 +++++++-------- dbrepo-search-service/init/Pipfile.lock | 82 +++++++-------- .../init/lib/dbrepo-1.7.0-py3-none-any.whl | Bin 31116 -> 31084 bytes .../init/lib/dbrepo-1.7.0.tar.gz | Bin 46110 -> 48573 bytes .../lib/dbrepo-1.7.0-py3-none-any.whl | Bin 31116 -> 31084 bytes dbrepo-search-service/lib/dbrepo-1.7.0.tar.gz | Bin 46110 -> 48573 bytes 23 files changed, 211 insertions(+), 200 deletions(-) diff --git a/dbrepo-analyse-service/Pipfile.lock b/dbrepo-analyse-service/Pipfile.lock index 0ad21ce99c..9e59a2fef8 100644 --- a/dbrepo-analyse-service/Pipfile.lock +++ b/dbrepo-analyse-service/Pipfile.lock @@ -384,44 +384,48 @@ }, "cryptography": { "hashes": [ - "sha256:00918d859aa4e57db8299607086f793fa7813ae2ff5a4637e318a25ef82730f7", - "sha256:1e8d181e90a777b63f3f0caa836844a1182f1f265687fac2115fcf245f5fbec3", - "sha256:1f9a92144fa0c877117e9748c74501bea842f93d21ee00b0cf922846d9d0b183", - "sha256:21377472ca4ada2906bc313168c9dc7b1d7ca417b63c1c3011d0c74b7de9ae69", - "sha256:24979e9f2040c953a94bf3c6782e67795a4c260734e5264dceea65c8f4bae64a", - "sha256:2a46a89ad3e6176223b632056f321bc7de36b9f9b93b2cc1cccf935a3849dc62", - "sha256:322eb03ecc62784536bc173f1483e76747aafeb69c8728df48537eb431cd1911", - "sha256:436df4f203482f41aad60ed1813811ac4ab102765ecae7a2bbb1dbb66dcff5a7", - "sha256:4f422e8c6a28cf8b7f883eb790695d6d45b0c385a2583073f3cec434cc705e1a", - "sha256:53f23339864b617a3dfc2b0ac8d5c432625c80014c25caac9082314e9de56f41", - "sha256:5fed5cd6102bb4eb843e3315d2bf25fede494509bddadb81e03a859c1bc17b83", - "sha256:610a83540765a8d8ce0f351ce42e26e53e1f774a6efb71eb1b41eb01d01c3d12", - "sha256:6c8acf6f3d1f47acb2248ec3ea261171a671f3d9428e34ad0357148d492c7864", - "sha256:6f76fdd6fd048576a04c5210d53aa04ca34d2ed63336d4abd306d0cbe298fddf", - "sha256:72198e2b5925155497a5a3e8c216c7fb3e64c16ccee11f0e7da272fa93b35c4c", - "sha256:887143b9ff6bad2b7570da75a7fe8bbf5f65276365ac259a5d2d5147a73775f2", - "sha256:888fcc3fce0c888785a4876ca55f9f43787f4c5c1cc1e2e0da71ad481ff82c5b", - "sha256:8e6a85a93d0642bd774460a86513c5d9d80b5c002ca9693e63f6e540f1815ed0", - "sha256:94f99f2b943b354a5b6307d7e8d19f5c423a794462bde2bf310c770ba052b1c4", - "sha256:9b336599e2cb77b1008cb2ac264b290803ec5e8e89d618a5e978ff5eb6f715d9", - "sha256:a2d8a7045e1ab9b9f803f0d9531ead85f90c5f2859e653b61497228b18452008", - "sha256:b8272f257cf1cbd3f2e120f14c68bff2b6bdfcc157fafdee84a1b795efd72862", - "sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009", - "sha256:d9c5b9f698a83c8bd71e0f4d3f9f839ef244798e5ffe96febfa9714717db7af7", - "sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f", - "sha256:df978682c1504fc93b3209de21aeabf2375cb1571d4e61907b3e7a2540e83026", - "sha256:e403f7f766ded778ecdb790da786b418a9f2394f36e8cc8b796cc056ab05f44f", - "sha256:eb3889330f2a4a148abead555399ec9a32b13b7c8ba969b72d8e500eb7ef84cd", - "sha256:f4daefc971c2d1f82f03097dc6f216744a6cd2ac0f04c68fb935ea2ba2a0d420", - "sha256:f51f5705ab27898afda1aaa430f34ad90dc117421057782022edf0600bec5f14", - "sha256:fd0ee90072861e276b0ff08bd627abec29e32a53b2be44e41dbcdf87cbee2b00" + "sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390", + "sha256:0529b1d5a0105dd3731fa65680b45ce49da4d8115ea76e9da77a875396727b41", + "sha256:1bc312dfb7a6e5d66082c87c34c8a62176e684b6fe3d90fcfe1568de675e6688", + "sha256:268e4e9b177c76d569e8a145a6939eca9a5fec658c932348598818acf31ae9a5", + "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1", + "sha256:2bf7bf75f7df9715f810d1b038870309342bff3069c5bd8c6b96128cb158668d", + "sha256:3b721b8b4d948b218c88cb8c45a01793483821e709afe5f622861fc6182b20a7", + "sha256:3c00b6b757b32ce0f62c574b78b939afab9eecaf597c4d624caca4f9e71e7843", + "sha256:3dc62975e31617badc19a906481deacdeb80b4bb454394b4098e3f2525a488c5", + "sha256:4973da6ca3db4405c54cd0b26d328be54c7747e89e284fcff166132eb7bccc9c", + "sha256:4e389622b6927d8133f314949a9812972711a111d577a5d1f4bee5e58736b80a", + "sha256:51e4de3af4ec3899d6d178a8c005226491c27c4ba84101bfb59c901e10ca9f79", + "sha256:5f6f90b72d8ccadb9c6e311c775c8305381db88374c65fa1a68250aa8a9cb3a6", + "sha256:6210c05941994290f3f7f175a4a57dbbb2afd9273657614c506d5976db061181", + "sha256:6f101b1f780f7fc613d040ca4bdf835c6ef3b00e9bd7125a4255ec574c7916e4", + "sha256:7bdcd82189759aba3816d1f729ce42ffded1ac304c151d0a8e89b9996ab863d5", + "sha256:7ca25849404be2f8e4b3c59483d9d3c51298a22c1c61a0e84415104dacaf5562", + "sha256:81276f0ea79a208d961c433a947029e1a15948966658cf6710bbabb60fcc2639", + "sha256:8cadc6e3b5a1f144a039ea08a0bdb03a2a92e19c46be3285123d32029f40a922", + "sha256:8e0ddd63e6bf1161800592c71ac794d3fb8001f2caebe0966e77c5234fa9efc3", + "sha256:909c97ab43a9c0c0b0ada7a1281430e4e5ec0458e6d9244c0e821bbf152f061d", + "sha256:96e7a5e9d6e71f9f4fca8eebfd603f8e86c5225bb18eb621b2c1e50b290a9471", + "sha256:9a1e657c0f4ea2a23304ee3f964db058c9e9e635cc7019c4aa21c330755ef6fd", + "sha256:9eb9d22b0a5d8fd9925a7764a054dca914000607dff201a24c791ff5c799e1fa", + "sha256:af4ff3e388f2fa7bff9f7f2b31b87d5651c45731d3e8cfa0944be43dff5cfbdb", + "sha256:b042d2a275c8cee83a4b7ae30c45a15e6a4baa65a179a0ec2d78ebb90e4f6699", + "sha256:bc821e161ae88bfe8088d11bb39caf2916562e0a2dc7b6d56714a48b784ef0bb", + "sha256:c505d61b6176aaf982c5717ce04e87da5abc9a36a5b39ac03905c4aafe8de7aa", + "sha256:c63454aa261a0cf0c5b4718349629793e9e634993538db841165b3df74f37ec0", + "sha256:c7362add18b416b69d58c910caa217f980c5ef39b23a38a0880dfd87bdf8cd23", + "sha256:d03806036b4f89e3b13b6218fefea8d5312e450935b1a2d55f0524e2ed7c59d9", + "sha256:d1b3031093a366ac767b3feb8bcddb596671b3aaff82d4050f984da0c248b615", + "sha256:d1c3572526997b36f245a96a2b1713bf79ce99b271bbcf084beb6b9b075f29ea", + "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7", + "sha256:f514ef4cd14bb6fb484b4a60203e912cfcb64f2ab139e88c2274511514bf7308" ], "markers": "python_version >= '3.7' and python_full_version not in '3.9.0, 3.9.1'", - "version": "==44.0.1" + "version": "==44.0.2" }, "dbrepo": { "hashes": [ - "sha256:83a135d0c054d8420f64029eabd9a630380cce0c5963cdafc661a677593f2553" + "sha256:7ba35243c4ead72be2bf2a2d00a3fbbae4a9c7dabb872cca8ed1b1ce77720b5d" ], "path": "./lib/dbrepo-1.7.0.tar.gz" }, @@ -2186,12 +2190,12 @@ }, "pytest": { "hashes": [ - "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", - "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761" + "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", + "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==8.3.4" + "version": "==8.3.5" }, "python-dateutil": { "hashes": [ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.7.0-py3-none-any.whl b/dbrepo-analyse-service/lib/dbrepo-1.7.0-py3-none-any.whl index 08a42f973e93b8acbd66e40d29ef12ad4fe19ffa..385c9e224a31ae8811c03908303ea42fc2374d0a 100644 GIT binary patch delta 5477 zcmeDA%=qRL<Axgsd<pSMQP+ca>+Tm}U^tSz`I$jHW4-Dbl_X7}1HNTtkB%NbXvSl^ zR8N{E$$7(t<=JtGpFS~%>qh)AE!$MK?J%p&-)Dsz<}WPna9X|3i!-*C`%{mSSDC*0 zltZ?C9OVp(XQwS*_dx$qiPO4#sR<`eU0!;|N-etI%Ch#O)iarneDT>LSI-9SxNEC= zKD6`PakW$l?Ppf?Efy_0=M42rq6MByTvUHG(YA1H%fuBoEU#BQSu+2y#&zR`(_GfM zy;r}d)U$_!d6B}A1!o;EDCjwCF%ds{cY~DYYM$byf%?bm8(%K6%rZO{^VYItp6nap zbsN{Dxhso#&+1JoR*F^lmgjEU)x1+st4Ahr)va$K5_)dm6IN!eYOX(Mc4^Vy;zNhk z<j=0V+L+-#-{S)7md&-V=H6Nml%G-Z``L{Hd%Zl~PgT<CX<f);uK(zQsN8wpq{_Yp z`O?1wg;;8o&VE!{<kEPz`7GbuUtfgmEv5&GGiNAH`k=Kw;_`u=Ga}kNB7L-qTs}NJ zU^T;(wKXp;d#5(1!wlhz$;W?W*B8m8JuGp)lXT;q^r^%a+t2T=eGBRGtyz#&D04Aa zNVu%7=9Sd;yN&ASPtG(v>L)2bjpgU|BRzcv;dA+X7Tz_R8@~I_L!RK5q4r-h`kW<% z{r=Ai|Ic(f=}kdpCFlM{UOF=@4mTG}xB7gbZCyUs2JP70&mP5m(!8`cL^p<O!`TD% z8=D(59wwh=w#j#~XQ<w9<a0M_Uwp^C^MbvdNB?e=V>RjCD8MK2u`K+-j-oBb``im| zXJ%}UbZchbdYQrG?F#P3*D}6LQTtX1|7DP8Sv1M*cyO-jk5axemF#z0r>?5mw0KQj ziq4j+?16iiHp<Qoda<VQ@blX~$sZF<qWfHeed?PpU*p~$*}d|A;;LygYC1Q%UR`F& z<$SGrUA*+{olRdly@l<Yr>|W#J?HGNbJMz|uU_VEuD#~JWkuW~)z^#l&58rHzm;!F zTf3fz_sy9E=cQS`kxMPieO9isn0zZ@iBmDZ^Ny!N1)Tw%GoIb)6`1n#j(kvrrmUIg z!%Jps&VG<GuaDTe^!JuBqv))Fou8egU$2`!`=XEd)Vvdq%??J@=A2nNL$B~hO7ET6 z>}4%a4HZ`#_Ett|f1Bj>Z0A0+tv}~ZkuqNsIeXPKQ~8pY73xZR{C581SzH%?Jbbgu z$*ZOYYkS?UnrPgNnB|b!zBF3Hc9G$|MoGJ5=^ahIeF`^2on4yiKO`l`%se#1;z7cN zYZs1fDB)kKuG1)$6Vk-?H|Oem<th6Xc{ctMTiNf>rh95Z{sB+n9OgOEM=Y7nZ98!@ zgKKGXk?>2U2qwGjC!TXWxxGrDfO)CyE~O7ImFFivIO-Ue*LdDNo>fvZX#>j~%M&-5 zHn4O&Rd%QgouDwWS*X`Bov;4Yn{T!O700%zZfT8}q{zE-p3}>QrG_V-8$8`{DRm=@ zNX(KA4Cnc$TyB=VvtCQ(L_>q>0>25ndYH60UMT1~W~wvnbUtzNeZVha?}T>QTZv3D z?<c(G{PCRc?`Jl(gSLK+<_Dh3{hZU-YqRB|?uqX!o=j#Isocq0)$ifYuEVnNPQBAh zL2q+~w{lDOGOm7eQ7d@Dw}wl8jrSN|`hp3^X7(!&L{`X8_$BhC$YHNf;~_>(i3Gzg zF=K{FN=q0o1x>leus7gJH{+gwCr26LG(IIUu&&ZLP_f+NUjBmnabG7Jiaz}<d+Xnk zZTAnx{|k}hjH+_cz1#Fx?qc0`g~Q6H>I=BP$W6S*Wn<~&zmIiJKbQK6?<>}DZn9tW zX8Qx%{uj2}6)q}!m2fY9^>N8EGs~5UoGBjy+9WT0o^a2{uRd!Ni*#kiV#yQF7uFbC zwyruUyrSBpmhaO~jr%ewA40D%`2JYYY58Mjf1TO%%~Fr{FrNE%;-*Z+$BEM|Gp@V8 zJ*Sve|3ktwOd+@B(z(WL`JHhMZx~PQW8i9(djG(dvFbe24!#MmSu6Y-?rm-p3Kryf z!RnFED8&=d%)LNPp_DmgfyUt?9j}GWsvFWeuEjLfD4yEhk|C9365GV)eC2`c0~@7t z))U@$e7ei{L{L%v!nWYt1wWOu{_&aAyPVz6oL%RZUB9lOs^v<!LST!~S_UJh6Q&ME zTRoU~jjlY9T4B6oAKOjIQ~TI5CB1gDaq(!bIjF_6b`ykapPV&s8n@Bb7N*q(TTVsk zEe+VmdVzbwJiaKU6-!M$j!bbeFq7;%YwBRc%6aebg=(J#a>}K`$KuzB9a_*SVVc;a zmUN{>^Ll;r%TMB7Ssz*IWLH;8soYxRqL!iL<~!qp*lM!}#%^}L7t(uvnK*uvNHuqC zHq5%fl9@cEj5$XA#8);2;g&lL(^xj<C~Q)fxcT0(O?}EkxgRx7cJCX{t3UZ{oAF4} z)R1ki<%-RmQ_3Q$`2Wt^cwc_Obo~|6`5hj%h}bba;Z(G*XKG#V@lg53x9mx}x}j+? z?}ArHC!V;IGCN|0$m|`7)7o`Z^L{63<*hycHg$(ehijgqQRbV_?;o<xa<5JDJ@b8z z$=lCq8`M$`l-o^st2uwG%%dMC+V=lDHEFTOzrBsl`uk#Qh24I~Tk8A{y&CgVWt;0m zFSXir^ZxxjuRZ^L^3jj=$6vmZ=v+K;hS0bA{Pjr(JqsP<JeGAn+vVav>r}w*2B%%l zS{kj4g;#g_`iAZG&b6P_z4dR%!-dl}2mM-^_3gFJ!t3*->~7raj9Y@Aiz<B#i~ ztX}ceCR|shJSt%lOP>3&0(OO^Ia*<9i#O^%4{zJ*wP?Ea0SlEdp^Mw*yx3eXyHo7G zaej2Cw}Fh%ThFhPq@+VW-(S?XX#YZ^SEW}Tq#D1Pu;AGqv-L|&bah*@W!}9!StHOM zx5NIch1KcD)@~{8`%_ZOwk$p$r?*;u=kA!!?_2xIbe>IJx48F7gmC@Q7$cb-S30{J ziYDbSiyw6_N-EvEzSBLc>Ux88!OKNVFY8<TVtYb*3S2uP^~yi^<b>Z)4L$Z;r6;=I zH`769oz{G|z30>&*o}B&9$w&NZkKt?=kL#Si*1oc;gOQ^UCVp&R=PjF>@D-id(P?S z+a{k$vS>WKzVGlq<NgIZrd9aQW-~Oe={sey+TCJdO6mN?3>s3uVz^$~6|A1P?cfeu zKjG&3BcG3CI{%2VSoFI5&3C19%&VR&zU_WGF+u+M`NY%H6(s(8Ma{Z9&1_=R`T4V& z8d;=WnN;%FS6!`r#eB6|obm6RCFRXrFLwQDs9yAWMb)BxyMD<izq)<#<Rivcd-`@8 zD3!=Z7;Snwr(8)o@8rt&OP8>I-<h*1>ab1KxrdWK+`Lm#-)dZVm-9-I>9k7gAMQ&F z66#OZhj0}z&bIm3eRAQ{H!5|T-_Dsf_gfwR=bg@v>x^o&_b1HldtKDmqNzXo->GU# zCeQ0Z+zC}{A9+nMih3Ss{xgnWC)Rtf&z-tG*UDFHstMaK7i?hV_C0IuJ?nqPXMatP zSdn@El8Ma!-)#x|`RePZUktmmK~q2DLtmTg>#mANze?HeS><?dpSv_sTjSExSe2*) zj#>uVIa-#b=GOKTSQnnxV&?7Hn#UCNWBvZg>_JyH^gHj^p|k47H^+7R6YeYA^}ORE z(RJD(lH2;p_WKhAGMu<~?rHxNw1?AbdTrH-r`B5DH-CjVt$(^gdK>SJS@nOSOD}WH z?Bw#FvGK)GmU!>aS94!)-TNjlRr!Rl>iM?<4$D{H<vMhtU0pDD#R>68Dzb`JljhCs zcHo`1nx`=?s+&WYSGPQ-IACf{*i)sdbH`(UUlG2<-+XLttf{lsAqUm2vS*>^_rJPj z@#5&&y@vvOSEOu|RoCI)-!^N@^~l5f>-E;Hun6Mdt!+N^^WlT~#s~KL0)O^8ADCls z?W>zN->olC+S&TwuDs;#9dk9OG4TAUA3yZ=M0muXyy`UhKyK^WW6SgR^xv0SvZ?x` zzWl-}mxb3NK7{iGEq(e+J-K(iR6)%4SFxM)+j~~6o+~~}-hR&Hq-Bh~n(j(ZbW`Si zmP}Q2S6enI@KDSGjhid;5BZ(jyp?NB=q;<8Mndzo7cDY-y2X-TH0Vj^XWNjoyEK-@ zNw;r&o4RgR9Ge{9rNr=p7V*j-pPbi5ecG=!S>EnCWAEngcITMt8$0~V->C%YR~*?8 zlNXk3`?O3}ZK88g&AKn;(#fF@9uyx6ceCVUV2Etk*3<qpW3R~PfNQloQy0$Yzx0ob zMPNnPv}(z~Jt2R2xts62TUb_U5cT<FEziDnxkvA6tJglx@tc1AfQ0<5_6wo>c{|cd z^A5Edn8b&lxTtHF={iI3&17e%GR9?-cR97y|9;lz`Ygcbg^u2xExIyiMSed&KQ+Yr zzVWPWXAC&*ncM2*_g~i*d#YJq#%s3p(CJ_IQZ%1F&)W7>R`zQ6_qr3$nJ-opXz%|b zxj5I!Hazd-<*Y)_$TY#|_lBp}Bw2g>%G_7Bfg}CLHvO2LvN}6u|Lm}xQTV%1$!=!F z0>|4E=Sb9N<QllPSN?ooc<_10l}hK&o(_kf{@iSTn|03DU4{Q;%^#%RvdV3{Qo`x* zY-6;;heP#zYV`_%JHO6v_AWkicl)Q!KQ6w`+5PTZos>sa;)|cZ76>!g>=y3oH(o8T za=k&c_52!E72Ay&hEY{57nvr{i!eFxr2qOkxsuk4A=XUif7btt{k-F~R8sxsgP(=+ zqAmP>-BZ4NYisCB&yaT?cKukf>dT~8d-S<JeGPItHNTeU=On!wr;i)lud2CSBl!G` zw8h^;yQeIEy{)V~qT;1Tiv3&GlVt}!Ef+lZH%zU@^+xAuK9;zv>QR3<Zl4Og{{F4# z#PHBR-(KfGm)&-~uIA?(!HD|R;h&CL-Z;3=CMV8q=S%U0?MwUj?EA1`lJuANM?V#9 zYmVgJcPb){Qz=J3PeD84ou1mgxV=xW>#zROEwA&kb=4EawdZy<PVajw{{4xY=5Mpy z$A1*uW6P$@wR7?@KKC}>|3sWIU-8`2Chb4-e?58@rMhRW)r2=C><7<TcO3THdcL0F z>(-q{DPEJ`e|X%nYRa>S=zi16u4gySY`pu$J80R~8)rTQPcqc$OgWvDnVCHGF^|*f zvQ2lEy(nGlzvZk?Z9!1(YrX6(cjXSO{*cbHDn$C!2UD}UjE}SCEPcgz=zy0(@x;%! zo9=eC-)~g)kF{Rdz5Q8KO1{Oc^+s`lokjb+?(50xUY=WHcPI7aw!#?ugkSa(rzJjF zXw$PguF3nvC*@3@=TFlw%uL}I|IZZQ&CD{{uv}_0v)czI-dizAQO-w<?_@GDF!)XK zG_4m~8+Pw&KqS-bTWY!g_H8?!)_6A0JWxb0A?@4Q>U^7u=(SZ3tb3bR-B8fV6YZ!A zxOJ$%F#W=`54A3T3!2wXIK-vuy(4kj+ZhLi>Ndqb&zoQU?eyI|*Yv>YAAF0iMDBJv zw!d1&rooeS--dOeyWIbIW-r~W^Z3T0{P^7LtJhjS)m!!-eH9t`@b%S|IX_(YE{i;{ zyFburZsTqjZrM{dDdE*ud-s~K)-+^u{q{CaEO6D%U!OPg#f0YKwDl7sTdEuDvnJ&E z8YFBuyw|lZltt%tuA%82)_SuG2VyH&`KC81sHmihF0F2QxKilSO^wLyQ`fj>NCkOh z&fY2ZE0HmO*7N$+3RVjzg<La~QJufJd(y27(NCf$?Ge56+Bl58^vfn88;vDX*%h10 z-<zK-I9~Ip@|RZux4g`qMdjS;atp<CEZ_b3ygRqC^zM~UpWP(ipE@!@B7miZGa`QK z5oYoH=&sYQb$dU&*7ac$f3NvHbXM^)*Syt26FYW99?*^2ns=qNwm#%n=3h^11<pV3 z`|KiCv0XW%ReLDJbjH-hSsr<-4l1|551g8CNM-kw>TA8l{y~4{Xm7mc9c6SfdY7QZ z`ZXQZ*K60YPqA74zA{gqEoTwi|Cl(NgMMDcSMs($)N`C+x-@cDv7*BU`;UCxO;@z) zZFZXd;*9araP{NM;5l9SE%kANWKev*l|OI#g2Ftr>o)Oe@{{uY=XxtiZ%_K+JyE{w z>Z}#tJwFKTxbRM)?6`eu$YrZ<af@ZQ_Wb95@#jkc`(|4YlRcGB0yH1@9GMZ_ZWXfj z#6Lz*iW6aAVBlczElb+m<-L@j8N@J(t`P$<CT}d945r<SJUD&JlA^@EpMJVv@{A&_ z`qO=j93)sD)Y@}fh=_BGZGN!ogsY%Hs<Qx>?$e+Xt{-16pDZbCJ@?*O?i$PgCx3o^ z%scVf^q8$Kx`wNMOU_*JZqBAdf4=8g?|;_%e(udC?IWo#Oh3&P@Gaexu|DtlN51S? z*KEJ-s$3eu*&+Wk{!HfYf6`?YZF5^}74JMKN?+hypYqH5`7_R+m5Iw|?~P*p8N5kl zt8PUXE6?{s+gAMUo9mz^zGwNC_R@})*t{_3Q!=%dujd^+sW?6Gg^Oc$?Cq=-{@fcb zb#r^(T=LU=!-iE$ldimzo8M)4v-)I`Z@f-bxzQ|!s-AfknXeBwm<u>FI<n~Nc^35k zR;gTEvErrN&W?KTqy8^d3|4oDg=tCIY}p&u^m;<5i2jbv_7aLm_sp5{;D6TB+Rw)d zzMp+$bysfpq`=3C9Uq0unpWsfw&s1dLq}ixfmBq^buQ<PO$X{12Fx|J+_kqbd$0Yy z?aK3xNgrp}bj9s#_U)4`Yk&1TG%cNI_Jma~^W2ghJAbfNr*wSTv9f-*`TFT!iiBQm zHoN%o<&GeSInA{u@4R*xT3Csumc+JSlVH>IXFT!geZo|sPpWgu_})2jtF3VA&R&uv z<@aENhu&(Rk6dnvXH6=4xCQ3EwLV&;^qYV2L7sCnBKvmFJ63w}&nDl{^4h;g-QInQ zQ8^UmdojT^cy`1blQ0*fh>LX*^>YvXUb6CC-I-hSnHlFW)ECLxPB68c5dUF|*TaIh z3}?*Ge!B23PqfeZ{0HkA`5v2}H4`5dwyazG`_uD}GIRd3xO>NLkALObcz#Cl(#<bD zGUX0#<9U*K>W#C?Rh3?y>fb)IW7DE%I(t4)-<0nWv`BF3=6@IWXVmtc>AJY;Tg4PT zW!?nm3K!M0g8LTz<SjBk@3+wSP1HrlWpz1;t5?5X>lP?q&#*bJbQU8Y>UiU1wsL=_ zJ+6}(-NYy7m1{AbbeqiQE~Opd&B!Fe49N*7<t`@!14xts3YIh;n0&unSss)Z{s{2c z<?u5w#Og3G$U)^n)RM;N$%+-a;CvHUA<e`bJ=rl@adLkJ4_Ihkg)~!B;bg~X$;nqL z1QkFgB}OyVaWXJ4urn|)sDO-s;w6m|MPP;bMZA->D|wKzphKl7Q*zPdg+=m{%PIxf I>`Fme0HaG*lK=n! delta 5512 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 diff --git a/dbrepo-analyse-service/lib/dbrepo-1.7.0.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.7.0.tar.gz index df984d46425dbda00a0d6d3e2b037a271de0a379..823a773ca48627ae548e2e0448bef1f5a224b3d8 100644 GIT binary patch literal 48573 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 literal 46110 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 diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index 8a16c455d8..ab306ea608 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -279,7 +279,6 @@ public class TableEndpoint extends RestEndpoint { log.debug("timestamp not set: default to {}", timestamp); } final TableDto table = cacheService.getTable(databaseId, tableId); - final DatabaseDto database = cacheService.getDatabase(databaseId); if (!table.getIsPublic()) { if (principal == null) { log.error("Failed find table data: authentication required"); @@ -287,6 +286,7 @@ public class TableEndpoint extends RestEndpoint { } cacheService.getAccess(databaseId, getId(principal)); } + final DatabaseDto database = cacheService.getDatabase(databaseId); try { final HttpHeaders headers = new HttpHeaders(); if (request.getMethod().equals("HEAD")) { diff --git a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java index cf3f25fd26..0926b1cf02 100644 --- a/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java +++ b/dbrepo-data-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java @@ -458,6 +458,13 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { return generic_handle(e.getClass(), e.getLocalizedMessage()); } + @Hidden + @ResponseStatus(code = HttpStatus.CONFLICT) + @ExceptionHandler(ViewExistsException.class) + public ResponseEntity<ApiErrorDto> handle(ViewExistsException e) { + return generic_handle(e.getClass(), e.getLocalizedMessage()); + } + @Hidden @ResponseStatus(code = HttpStatus.BAD_REQUEST) @ExceptionHandler(ViewMalformedException.class) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java index 709e389386..e03ea299a2 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/config/MariaDbConfig.java @@ -30,10 +30,10 @@ public class MariaDbConfig { log.debug("created database {}", database); } - public static void createInitDatabase(ContainerDto container, DatabaseDto database) throws SQLException { - final String jdbc = "jdbc:mariadb://" + container.getHost() + ":" + container.getPort(); + public static void createInitDatabase(DatabaseDto database) throws SQLException { + final String jdbc = "jdbc:mariadb://" + database.getContainer().getHost() + ":" + database.getContainer().getPort(); log.trace("connect to database {}", jdbc); - try (Connection connection = DriverManager.getConnection(jdbc, container.getUsername(), container.getPassword())) { + try (Connection connection = DriverManager.getConnection(jdbc, database.getContainer().getUsername(), database.getContainer().getPassword())) { ResourceDatabasePopulator populator = new ResourceDatabasePopulator(new ClassPathResource("init/" + database.getInternalName() + ".sql"), new ClassPathResource("init/users.sql"), new ClassPathResource("init/querystore.sql")); populator.setSeparator(";\n"); populator.populate(connection); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java index 765a7f0cd3..25f3b60cea 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java @@ -4,6 +4,7 @@ import at.tuwien.api.database.DatabaseAccessDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.query.ImportDto; import at.tuwien.api.database.table.*; +import at.tuwien.api.database.table.internal.TableCreateDto; import at.tuwien.endpoints.TableEndpoint; import at.tuwien.exception.*; import at.tuwien.gateway.MetadataServiceGateway; @@ -103,9 +104,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getDatabase(DATABASE_1_ID)) .thenReturn(DATABASE_1_PRIVILEGED_DTO); - when(databaseService.createTable(DATABASE_1_DTO, TABLE_4_CREATE_INTERNAL_DTO)) + when(databaseService.createTable(any(DatabaseDto.class), any(TableCreateDto.class))) .thenReturn(TABLE_4_DTO); - when(databaseService.inspectTable(DATABASE_1_DTO, TABLE_4_INTERNALNAME)) + when(databaseService.inspectTable(any(DatabaseDto.class), anyString())) .thenReturn(TABLE_4_DTO); /* test */ @@ -193,8 +194,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) .thenReturn(TABLE_8_DTO); - when(credentialService.getDatabase(DATABASE_1_ID)) - .thenReturn(DATABASE_1_PRIVILEGED_DTO); + when(credentialService.getDatabase(DATABASE_3_ID)) + .thenReturn(DATABASE_3_PRIVILEGED_DTO); doThrow(SQLException.class) .when(tableService) .getStatistics(any(DatabaseDto.class), any(TableDto.class)); @@ -279,7 +280,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1_PRIVILEGED_DTO); doThrow(SQLException.class) .when(tableService) - .delete(DATABASE_1_DTO, TABLE_1_DTO); + .delete(any(DatabaseDto.class), any(TableDto.class)); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { @@ -295,17 +296,17 @@ public class TableEndpointUnitTest extends AbstractUnitTest { final Dataset<Row> mock = sparkSession.emptyDataFrame(); /* mock */ - when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_DTO); - when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_PRIVILEGED_DTO); + when(credentialService.getTable(DATABASE_1_ID, TABLE_4_ID)) + .thenReturn(TABLE_4_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(subsetService.getData(any(DatabaseDto.class), anyString())) .thenReturn(mock); when(httpServletRequest.getMethod()) .thenReturn("GET"); /* test */ - final ResponseEntity<List<Map<String, Object>>> response = tableEndpoint.getData(DATABASE_3_ID, TABLE_8_ID, null, null, null, httpServletRequest, null); + final ResponseEntity<List<Map<String, Object>>> response = tableEndpoint.getData(DATABASE_1_ID, TABLE_4_ID, null, null, null, httpServletRequest, null); assertEquals(HttpStatus.OK, response.getStatusCode()); } @@ -318,19 +319,19 @@ public class TableEndpointUnitTest extends AbstractUnitTest { final Dataset<Row> mock = sparkSession.emptyDataFrame(); /* mock */ - when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_DTO); - when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_PRIVILEGED_DTO); + when(credentialService.getTable(DATABASE_2_ID, TABLE_5_ID)) + .thenReturn(TABLE_5_DTO); + when(credentialService.getDatabase(DATABASE_2_ID)) + .thenReturn(DATABASE_2_PRIVILEGED_DTO); when(tableService.getCount(any(DatabaseDto.class), any(TableDto.class), any(Instant.class))) .thenReturn(3L); - when(subsetService.getData(eq(DATABASE_3_DTO), anyString())) + when(subsetService.getData(eq(DATABASE_2_DTO), anyString())) .thenReturn(mock); when(httpServletRequest.getMethod()) .thenReturn("HEAD"); /* test */ - final ResponseEntity<List<Map<String, Object>>> response = tableEndpoint.getData(DATABASE_3_ID, TABLE_8_ID, null, null, null, httpServletRequest, null); + final ResponseEntity<List<Map<String, Object>>> response = tableEndpoint.getData(DATABASE_2_ID, TABLE_5_ID, null, null, null, httpServletRequest, null); assertEquals(HttpStatus.OK, response.getStatusCode()); assertNotNull(response.getHeaders().get("Access-Control-Expose-Headers")); assertEquals("X-Count", response.getHeaders().get("Access-Control-Expose-Headers").get(0)); @@ -374,14 +375,31 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void getData_unavailable_fails() throws TableNotFoundException, RemoteUnavailableException, - MetadataServiceException, QueryMalformedException, DatabaseNotFoundException { + public void getData_notAllowed_fails() throws TableNotFoundException, RemoteUnavailableException, + MetadataServiceException{ /* mock */ when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) .thenReturn(TABLE_8_DTO); - when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_DTO); + when(httpServletRequest.getMethod()) + .thenReturn("GET"); + + /* test */ + assertThrows(NotAllowedException.class, () -> { + tableEndpoint.getData(DATABASE_3_ID, TABLE_8_ID, null, null, null, httpServletRequest, null); + }); + } + + @Test + @WithAnonymousUser + public void getData_unavailable_fails() throws TableNotFoundException, RemoteUnavailableException, + MetadataServiceException, QueryMalformedException, DatabaseNotFoundException { + + /* mock */ + when(credentialService.getTable(DATABASE_2_ID, TABLE_5_ID)) + .thenReturn(TABLE_5_DTO); + when(credentialService.getDatabase(DATABASE_2_ID)) + .thenReturn(DATABASE_2_DTO); doThrow(QueryMalformedException.class) .when(subsetService) .getData(any(DatabaseDto.class), anyString()); @@ -390,7 +408,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(DatabaseUnavailableException.class, () -> { - tableEndpoint.getData(DATABASE_3_ID, TABLE_8_ID, null, null, null, httpServletRequest, null); + tableEndpoint.getData(DATABASE_2_ID, TABLE_5_ID, null, null, null, httpServletRequest, null); }); } @@ -1186,15 +1204,15 @@ public class TableEndpointUnitTest extends AbstractUnitTest { RemoteUnavailableException, SQLException, NotAllowedException, MetadataServiceException, PaginationException, DatabaseNotFoundException { /* mock */ - when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_DTO); - when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_PRIVILEGED_DTO); - when(tableService.history(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, null)) + when(credentialService.getTable(DATABASE_2_ID, TABLE_5_ID)) + .thenReturn(TABLE_5_DTO); + when(credentialService.getDatabase(DATABASE_2_ID)) + .thenReturn(DATABASE_2_PRIVILEGED_DTO); + when(tableService.history(DATABASE_2_PRIVILEGED_DTO, TABLE_5_DTO, null)) .thenReturn(List.of()); /* test */ - final ResponseEntity<List<TableHistoryDto>> response = tableEndpoint.getHistory(DATABASE_3_ID, TABLE_8_ID, null, null); + final ResponseEntity<List<TableHistoryDto>> response = tableEndpoint.getHistory(DATABASE_2_ID, TABLE_5_ID, null, null); assertEquals(HttpStatus.OK, response.getStatusCode()); } @@ -1271,17 +1289,17 @@ public class TableEndpointUnitTest extends AbstractUnitTest { TableNotFoundException, MetadataServiceException, DatabaseNotFoundException { /* mock */ - when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_DTO); - when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_PRIVILEGED_DTO); + when(credentialService.getTable(DATABASE_2_ID, TABLE_5_ID)) + .thenReturn(TABLE_5_DTO); + when(credentialService.getDatabase(DATABASE_2_ID)) + .thenReturn(DATABASE_2_PRIVILEGED_DTO); doThrow(SQLException.class) .when(tableService) - .history(DATABASE_3_PRIVILEGED_DTO, TABLE_8_DTO, 100L); + .history(any(DatabaseDto.class), any(TableDto.class), anyLong()); /* test */ assertThrows(DatabaseUnavailableException.class, () -> { - tableEndpoint.getHistory(DATABASE_3_ID, TABLE_8_ID, null, null); + tableEndpoint.getHistory(DATABASE_2_ID, TABLE_5_ID, null, null); }); } @@ -1310,15 +1328,15 @@ public class TableEndpointUnitTest extends AbstractUnitTest { final Dataset<Row> mock = sparkSession.emptyDataFrame(); /* mock */ - when(credentialService.getTable(DATABASE_3_ID, TABLE_8_ID)) - .thenReturn(TABLE_8_DTO); - when(credentialService.getDatabase(DATABASE_3_ID)) - .thenReturn(DATABASE_3_PRIVILEGED_DTO); + when(credentialService.getTable(DATABASE_1_ID, TABLE_4_ID)) + .thenReturn(TABLE_4_DTO); + when(credentialService.getDatabase(DATABASE_1_ID)) + .thenReturn(DATABASE_1_PRIVILEGED_DTO); when(subsetService.getData(any(DatabaseDto.class), anyString())) .thenReturn(mock); /* test */ - final ResponseEntity<InputStreamResource> response = tableEndpoint.exportDataset(DATABASE_3_ID, TABLE_8_ID, null, null); + final ResponseEntity<InputStreamResource> response = tableEndpoint.exportDataset(DATABASE_1_ID, TABLE_4_ID, null, null); assertEquals(HttpStatus.OK, response.getStatusCode()); } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java index bf58d0fba1..d07123796c 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/gateway/MetadataServiceGatewayUnitTest.java @@ -104,27 +104,6 @@ public class MetadataServiceGatewayUnitTest extends AbstractUnitTest { }); } - @Test - public void getTableById_headerMissing_fails() { - final List<String> customHeaders = List.of("X-Username", "X-Password"); - - for (int i = 0; i < customHeaders.size(); i++) { - final HttpHeaders headers = new HttpHeaders(); - for (int j = 0; j < i; j++) { - headers.add(customHeaders.get(j), ""); - } - /* mock */ - when(internalRestTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(HttpEntity.EMPTY), eq(TableDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.OK) - .headers(headers) - .body(TABLE_1_DTO)); - /* test */ - assertThrows(MetadataServiceException.class, () -> { - metadataServiceGateway.getTableById(DATABASE_1_ID, TABLE_1_ID); - }); - } - } - @Test public void getTableById_emptyBody_fails() { final HttpHeaders headers = new HttpHeaders(); diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java index 2ebb4be18d..bf63189bf2 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerIntegrationTest.java @@ -59,7 +59,7 @@ public class DefaultListenerIntegrationTest extends AbstractUnitTest { genesis(); /* database */ MariaDbConfig.dropAllDatabases(CONTAINER_1_PRIVILEGED_DTO); - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_DTO); + MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); } @Test diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java index 3beec79ab2..686a134dc5 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/listener/DefaultListenerUnitTest.java @@ -54,8 +54,8 @@ public class DefaultListenerUnitTest extends AbstractUnitTest { public void beforeEach() throws SQLException { genesis(); /* metadata database */ - MariaDbConfig.dropAllDatabases(CONTAINER_1_DTO); - MariaDbConfig.createInitDatabase(CONTAINER_1_DTO, DATABASE_1_DTO); + MariaDbConfig.dropAllDatabases(CONTAINER_1_PRIVILEGED_DTO); + MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); } @Test diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/AccessServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/AccessServiceIntegrationTest.java index 2c174e0a3d..abcfd4a175 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/AccessServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/AccessServiceIntegrationTest.java @@ -45,7 +45,7 @@ public class AccessServiceIntegrationTest extends AbstractUnitTest { genesis(); /* metadata database */ MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_PRIVILEGED_DTO); + MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); } @Test diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java index 0bd3edc698..40fdb982ab 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceIntegrationTest.java @@ -63,9 +63,9 @@ public class DatabaseServiceIntegrationTest extends AbstractUnitTest { genesis(); /* metadata database */ MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_DTO); + MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_DTO); + MariaDbConfig.createInitDatabase(DATABASE_2_PRIVILEGED_DTO); Thread.sleep(1000) /* wait for test container some more */; } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java index 8ea5e9a973..6996ecb9f4 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java @@ -2,7 +2,10 @@ package at.tuwien.service; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.MariaDbContainerConfig; -import at.tuwien.exception.*; +import at.tuwien.exception.DatabaseNotFoundException; +import at.tuwien.exception.MetadataServiceException; +import at.tuwien.exception.RemoteUnavailableException; +import at.tuwien.exception.TableNotFoundException; import at.tuwien.gateway.MetadataServiceGateway; import at.tuwien.service.impl.QueueServiceRabbitMqImpl; import at.tuwien.test.AbstractUnitTest; @@ -49,8 +52,8 @@ public class QueueServiceIntegrationTest extends AbstractUnitTest { public void beforeEach() throws SQLException { genesis(); /* metadata database */ - MariaDbConfig.dropDatabase(CONTAINER_1_DTO, DATABASE_1_INTERNALNAME); - MariaDbConfig.createInitDatabase(CONTAINER_1_DTO, DATABASE_1_DTO); + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); + MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); } @Test diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java index 6ec99aaa00..d5bfaa1bbb 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SubsetServiceIntegrationTest.java @@ -50,7 +50,7 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { genesis(); /* metadata database */ MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_PRIVILEGED_DTO); + MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); } @Test @@ -138,15 +138,6 @@ public class SubsetServiceIntegrationTest extends AbstractUnitTest { assertFalse(response.getIsPersisted()); } - @Test - public void create_illegalQuery_fails() { - - /* test */ - assertThrows(QueryStoreInsertException.class, () -> { - subsetService.create(DATABASE_1_PRIVILEGED_DTO, QUERY_1_SUBSET_DTO, QUERY_1_CREATED, USER_1_ID); - }); - } - @Test public void getData_succeeds() throws QueryMalformedException, TableNotFoundException { final List<List<String>> expected = List.of( diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java index 76c073831a..77e91361db 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java @@ -79,8 +79,8 @@ public class TableServiceIntegrationTest extends AbstractUnitTest { MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_2_INTERNALNAME); MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_3_INTERNALNAME); - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_PRIVILEGED_DTO); - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_3_PRIVILEGED_DTO); + MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); + MariaDbConfig.createInitDatabase(DATABASE_3_PRIVILEGED_DTO); /* s3 */ if (s3Client.listBuckets().buckets().stream().noneMatch(b -> b.name().equals(s3Config.getS3Bucket()))) { s3Client.createBucket(CreateBucketRequest.builder() diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java index 9953728632..5e99f4afbc 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java @@ -34,7 +34,7 @@ public class ViewServiceIntegrationTest extends AbstractUnitTest { genesis(); /* metadata database */ MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNALNAME); - MariaDbConfig.createInitDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_PRIVILEGED_DTO); + MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); } @Test diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java index 53880e19b6..35240f9753 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java @@ -4642,15 +4642,16 @@ public abstract class BaseTest { .tableId(TABLE_5_ID) .columns(new LinkedList<>(List.of(COLUMN_5_1_ID, COLUMN_5_2_ID))) .filter(new LinkedList<>(List.of(FilterDto.builder() + .type(FilterTypeDto.WHERE) .columnId(COLUMN_5_3_ID) .operatorId(IMAGE_1_OPERATORS_2_ID) .value("true") - .type(FilterTypeDto.WHERE) .build(), FilterDto.builder() .type(FilterTypeDto.AND) .build(), FilterDto.builder() + .type(FilterTypeDto.WHERE) .columnId(COLUMN_5_4_ID) .operatorId(IMAGE_1_OPERATORS_2_ID) .value("false") diff --git a/dbrepo-search-service/Pipfile.lock b/dbrepo-search-service/Pipfile.lock index d3b5ccfbe0..576a8b3555 100644 --- a/dbrepo-search-service/Pipfile.lock +++ b/dbrepo-search-service/Pipfile.lock @@ -332,44 +332,48 @@ }, "cryptography": { "hashes": [ - "sha256:00918d859aa4e57db8299607086f793fa7813ae2ff5a4637e318a25ef82730f7", - "sha256:1e8d181e90a777b63f3f0caa836844a1182f1f265687fac2115fcf245f5fbec3", - "sha256:1f9a92144fa0c877117e9748c74501bea842f93d21ee00b0cf922846d9d0b183", - "sha256:21377472ca4ada2906bc313168c9dc7b1d7ca417b63c1c3011d0c74b7de9ae69", - "sha256:24979e9f2040c953a94bf3c6782e67795a4c260734e5264dceea65c8f4bae64a", - "sha256:2a46a89ad3e6176223b632056f321bc7de36b9f9b93b2cc1cccf935a3849dc62", - "sha256:322eb03ecc62784536bc173f1483e76747aafeb69c8728df48537eb431cd1911", - "sha256:436df4f203482f41aad60ed1813811ac4ab102765ecae7a2bbb1dbb66dcff5a7", - "sha256:4f422e8c6a28cf8b7f883eb790695d6d45b0c385a2583073f3cec434cc705e1a", - "sha256:53f23339864b617a3dfc2b0ac8d5c432625c80014c25caac9082314e9de56f41", - "sha256:5fed5cd6102bb4eb843e3315d2bf25fede494509bddadb81e03a859c1bc17b83", - "sha256:610a83540765a8d8ce0f351ce42e26e53e1f774a6efb71eb1b41eb01d01c3d12", - "sha256:6c8acf6f3d1f47acb2248ec3ea261171a671f3d9428e34ad0357148d492c7864", - "sha256:6f76fdd6fd048576a04c5210d53aa04ca34d2ed63336d4abd306d0cbe298fddf", - "sha256:72198e2b5925155497a5a3e8c216c7fb3e64c16ccee11f0e7da272fa93b35c4c", - "sha256:887143b9ff6bad2b7570da75a7fe8bbf5f65276365ac259a5d2d5147a73775f2", - "sha256:888fcc3fce0c888785a4876ca55f9f43787f4c5c1cc1e2e0da71ad481ff82c5b", - "sha256:8e6a85a93d0642bd774460a86513c5d9d80b5c002ca9693e63f6e540f1815ed0", - "sha256:94f99f2b943b354a5b6307d7e8d19f5c423a794462bde2bf310c770ba052b1c4", - "sha256:9b336599e2cb77b1008cb2ac264b290803ec5e8e89d618a5e978ff5eb6f715d9", - "sha256:a2d8a7045e1ab9b9f803f0d9531ead85f90c5f2859e653b61497228b18452008", - "sha256:b8272f257cf1cbd3f2e120f14c68bff2b6bdfcc157fafdee84a1b795efd72862", - "sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009", - "sha256:d9c5b9f698a83c8bd71e0f4d3f9f839ef244798e5ffe96febfa9714717db7af7", - "sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f", - "sha256:df978682c1504fc93b3209de21aeabf2375cb1571d4e61907b3e7a2540e83026", - "sha256:e403f7f766ded778ecdb790da786b418a9f2394f36e8cc8b796cc056ab05f44f", - "sha256:eb3889330f2a4a148abead555399ec9a32b13b7c8ba969b72d8e500eb7ef84cd", - "sha256:f4daefc971c2d1f82f03097dc6f216744a6cd2ac0f04c68fb935ea2ba2a0d420", - "sha256:f51f5705ab27898afda1aaa430f34ad90dc117421057782022edf0600bec5f14", - "sha256:fd0ee90072861e276b0ff08bd627abec29e32a53b2be44e41dbcdf87cbee2b00" + "sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390", + "sha256:0529b1d5a0105dd3731fa65680b45ce49da4d8115ea76e9da77a875396727b41", + "sha256:1bc312dfb7a6e5d66082c87c34c8a62176e684b6fe3d90fcfe1568de675e6688", + "sha256:268e4e9b177c76d569e8a145a6939eca9a5fec658c932348598818acf31ae9a5", + "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1", + "sha256:2bf7bf75f7df9715f810d1b038870309342bff3069c5bd8c6b96128cb158668d", + "sha256:3b721b8b4d948b218c88cb8c45a01793483821e709afe5f622861fc6182b20a7", + "sha256:3c00b6b757b32ce0f62c574b78b939afab9eecaf597c4d624caca4f9e71e7843", + "sha256:3dc62975e31617badc19a906481deacdeb80b4bb454394b4098e3f2525a488c5", + "sha256:4973da6ca3db4405c54cd0b26d328be54c7747e89e284fcff166132eb7bccc9c", + "sha256:4e389622b6927d8133f314949a9812972711a111d577a5d1f4bee5e58736b80a", + "sha256:51e4de3af4ec3899d6d178a8c005226491c27c4ba84101bfb59c901e10ca9f79", + "sha256:5f6f90b72d8ccadb9c6e311c775c8305381db88374c65fa1a68250aa8a9cb3a6", + "sha256:6210c05941994290f3f7f175a4a57dbbb2afd9273657614c506d5976db061181", + "sha256:6f101b1f780f7fc613d040ca4bdf835c6ef3b00e9bd7125a4255ec574c7916e4", + "sha256:7bdcd82189759aba3816d1f729ce42ffded1ac304c151d0a8e89b9996ab863d5", + "sha256:7ca25849404be2f8e4b3c59483d9d3c51298a22c1c61a0e84415104dacaf5562", + "sha256:81276f0ea79a208d961c433a947029e1a15948966658cf6710bbabb60fcc2639", + "sha256:8cadc6e3b5a1f144a039ea08a0bdb03a2a92e19c46be3285123d32029f40a922", + "sha256:8e0ddd63e6bf1161800592c71ac794d3fb8001f2caebe0966e77c5234fa9efc3", + "sha256:909c97ab43a9c0c0b0ada7a1281430e4e5ec0458e6d9244c0e821bbf152f061d", + "sha256:96e7a5e9d6e71f9f4fca8eebfd603f8e86c5225bb18eb621b2c1e50b290a9471", + "sha256:9a1e657c0f4ea2a23304ee3f964db058c9e9e635cc7019c4aa21c330755ef6fd", + "sha256:9eb9d22b0a5d8fd9925a7764a054dca914000607dff201a24c791ff5c799e1fa", + "sha256:af4ff3e388f2fa7bff9f7f2b31b87d5651c45731d3e8cfa0944be43dff5cfbdb", + "sha256:b042d2a275c8cee83a4b7ae30c45a15e6a4baa65a179a0ec2d78ebb90e4f6699", + "sha256:bc821e161ae88bfe8088d11bb39caf2916562e0a2dc7b6d56714a48b784ef0bb", + "sha256:c505d61b6176aaf982c5717ce04e87da5abc9a36a5b39ac03905c4aafe8de7aa", + "sha256:c63454aa261a0cf0c5b4718349629793e9e634993538db841165b3df74f37ec0", + "sha256:c7362add18b416b69d58c910caa217f980c5ef39b23a38a0880dfd87bdf8cd23", + "sha256:d03806036b4f89e3b13b6218fefea8d5312e450935b1a2d55f0524e2ed7c59d9", + "sha256:d1b3031093a366ac767b3feb8bcddb596671b3aaff82d4050f984da0c248b615", + "sha256:d1c3572526997b36f245a96a2b1713bf79ce99b271bbcf084beb6b9b075f29ea", + "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7", + "sha256:f514ef4cd14bb6fb484b4a60203e912cfcb64f2ab139e88c2274511514bf7308" ], "markers": "python_version >= '3.7' and python_full_version not in '3.9.0, 3.9.1'", - "version": "==44.0.1" + "version": "==44.0.2" }, "dbrepo": { "hashes": [ - "sha256:83a135d0c054d8420f64029eabd9a630380cce0c5963cdafc661a677593f2553" + "sha256:7ba35243c4ead72be2bf2a2d00a3fbbae4a9c7dabb872cca8ed1b1ce77720b5d" ], "path": "./lib/dbrepo-1.7.0.tar.gz" }, @@ -1254,12 +1258,12 @@ }, "pytest": { "hashes": [ - "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", - "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761" + "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", + "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==8.3.4" + "version": "==8.3.5" }, "python-dateutil": { "hashes": [ @@ -2006,12 +2010,12 @@ }, "pytest": { "hashes": [ - "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", - "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761" + "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", + "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==8.3.4" + "version": "==8.3.5" }, "requests": { "hashes": [ diff --git a/dbrepo-search-service/init/Pipfile.lock b/dbrepo-search-service/init/Pipfile.lock index e73e76971a..9b7988600b 100644 --- a/dbrepo-search-service/init/Pipfile.lock +++ b/dbrepo-search-service/init/Pipfile.lock @@ -259,7 +259,7 @@ }, "dbrepo": { "hashes": [ - "sha256:83a135d0c054d8420f64029eabd9a630380cce0c5963cdafc661a677593f2553" + "sha256:7ba35243c4ead72be2bf2a2d00a3fbbae4a9c7dabb872cca8ed1b1ce77720b5d" ], "path": "./lib/dbrepo-1.7.0.tar.gz" }, @@ -951,12 +951,12 @@ }, "pytest": { "hashes": [ - "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", - "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761" + "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", + "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==8.3.4" + "version": "==8.3.5" }, "python-dateutil": { "hashes": [ @@ -1496,40 +1496,44 @@ }, "cryptography": { "hashes": [ - "sha256:00918d859aa4e57db8299607086f793fa7813ae2ff5a4637e318a25ef82730f7", - "sha256:1e8d181e90a777b63f3f0caa836844a1182f1f265687fac2115fcf245f5fbec3", - "sha256:1f9a92144fa0c877117e9748c74501bea842f93d21ee00b0cf922846d9d0b183", - "sha256:21377472ca4ada2906bc313168c9dc7b1d7ca417b63c1c3011d0c74b7de9ae69", - "sha256:24979e9f2040c953a94bf3c6782e67795a4c260734e5264dceea65c8f4bae64a", - "sha256:2a46a89ad3e6176223b632056f321bc7de36b9f9b93b2cc1cccf935a3849dc62", - "sha256:322eb03ecc62784536bc173f1483e76747aafeb69c8728df48537eb431cd1911", - "sha256:436df4f203482f41aad60ed1813811ac4ab102765ecae7a2bbb1dbb66dcff5a7", - "sha256:4f422e8c6a28cf8b7f883eb790695d6d45b0c385a2583073f3cec434cc705e1a", - "sha256:53f23339864b617a3dfc2b0ac8d5c432625c80014c25caac9082314e9de56f41", - "sha256:5fed5cd6102bb4eb843e3315d2bf25fede494509bddadb81e03a859c1bc17b83", - "sha256:610a83540765a8d8ce0f351ce42e26e53e1f774a6efb71eb1b41eb01d01c3d12", - "sha256:6c8acf6f3d1f47acb2248ec3ea261171a671f3d9428e34ad0357148d492c7864", - "sha256:6f76fdd6fd048576a04c5210d53aa04ca34d2ed63336d4abd306d0cbe298fddf", - "sha256:72198e2b5925155497a5a3e8c216c7fb3e64c16ccee11f0e7da272fa93b35c4c", - "sha256:887143b9ff6bad2b7570da75a7fe8bbf5f65276365ac259a5d2d5147a73775f2", - "sha256:888fcc3fce0c888785a4876ca55f9f43787f4c5c1cc1e2e0da71ad481ff82c5b", - "sha256:8e6a85a93d0642bd774460a86513c5d9d80b5c002ca9693e63f6e540f1815ed0", - "sha256:94f99f2b943b354a5b6307d7e8d19f5c423a794462bde2bf310c770ba052b1c4", - "sha256:9b336599e2cb77b1008cb2ac264b290803ec5e8e89d618a5e978ff5eb6f715d9", - "sha256:a2d8a7045e1ab9b9f803f0d9531ead85f90c5f2859e653b61497228b18452008", - "sha256:b8272f257cf1cbd3f2e120f14c68bff2b6bdfcc157fafdee84a1b795efd72862", - "sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009", - "sha256:d9c5b9f698a83c8bd71e0f4d3f9f839ef244798e5ffe96febfa9714717db7af7", - "sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f", - "sha256:df978682c1504fc93b3209de21aeabf2375cb1571d4e61907b3e7a2540e83026", - "sha256:e403f7f766ded778ecdb790da786b418a9f2394f36e8cc8b796cc056ab05f44f", - "sha256:eb3889330f2a4a148abead555399ec9a32b13b7c8ba969b72d8e500eb7ef84cd", - "sha256:f4daefc971c2d1f82f03097dc6f216744a6cd2ac0f04c68fb935ea2ba2a0d420", - "sha256:f51f5705ab27898afda1aaa430f34ad90dc117421057782022edf0600bec5f14", - "sha256:fd0ee90072861e276b0ff08bd627abec29e32a53b2be44e41dbcdf87cbee2b00" + "sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390", + "sha256:0529b1d5a0105dd3731fa65680b45ce49da4d8115ea76e9da77a875396727b41", + "sha256:1bc312dfb7a6e5d66082c87c34c8a62176e684b6fe3d90fcfe1568de675e6688", + "sha256:268e4e9b177c76d569e8a145a6939eca9a5fec658c932348598818acf31ae9a5", + "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1", + "sha256:2bf7bf75f7df9715f810d1b038870309342bff3069c5bd8c6b96128cb158668d", + "sha256:3b721b8b4d948b218c88cb8c45a01793483821e709afe5f622861fc6182b20a7", + "sha256:3c00b6b757b32ce0f62c574b78b939afab9eecaf597c4d624caca4f9e71e7843", + "sha256:3dc62975e31617badc19a906481deacdeb80b4bb454394b4098e3f2525a488c5", + "sha256:4973da6ca3db4405c54cd0b26d328be54c7747e89e284fcff166132eb7bccc9c", + "sha256:4e389622b6927d8133f314949a9812972711a111d577a5d1f4bee5e58736b80a", + "sha256:51e4de3af4ec3899d6d178a8c005226491c27c4ba84101bfb59c901e10ca9f79", + "sha256:5f6f90b72d8ccadb9c6e311c775c8305381db88374c65fa1a68250aa8a9cb3a6", + "sha256:6210c05941994290f3f7f175a4a57dbbb2afd9273657614c506d5976db061181", + "sha256:6f101b1f780f7fc613d040ca4bdf835c6ef3b00e9bd7125a4255ec574c7916e4", + "sha256:7bdcd82189759aba3816d1f729ce42ffded1ac304c151d0a8e89b9996ab863d5", + "sha256:7ca25849404be2f8e4b3c59483d9d3c51298a22c1c61a0e84415104dacaf5562", + "sha256:81276f0ea79a208d961c433a947029e1a15948966658cf6710bbabb60fcc2639", + "sha256:8cadc6e3b5a1f144a039ea08a0bdb03a2a92e19c46be3285123d32029f40a922", + "sha256:8e0ddd63e6bf1161800592c71ac794d3fb8001f2caebe0966e77c5234fa9efc3", + "sha256:909c97ab43a9c0c0b0ada7a1281430e4e5ec0458e6d9244c0e821bbf152f061d", + "sha256:96e7a5e9d6e71f9f4fca8eebfd603f8e86c5225bb18eb621b2c1e50b290a9471", + "sha256:9a1e657c0f4ea2a23304ee3f964db058c9e9e635cc7019c4aa21c330755ef6fd", + "sha256:9eb9d22b0a5d8fd9925a7764a054dca914000607dff201a24c791ff5c799e1fa", + "sha256:af4ff3e388f2fa7bff9f7f2b31b87d5651c45731d3e8cfa0944be43dff5cfbdb", + "sha256:b042d2a275c8cee83a4b7ae30c45a15e6a4baa65a179a0ec2d78ebb90e4f6699", + "sha256:bc821e161ae88bfe8088d11bb39caf2916562e0a2dc7b6d56714a48b784ef0bb", + "sha256:c505d61b6176aaf982c5717ce04e87da5abc9a36a5b39ac03905c4aafe8de7aa", + "sha256:c63454aa261a0cf0c5b4718349629793e9e634993538db841165b3df74f37ec0", + "sha256:c7362add18b416b69d58c910caa217f980c5ef39b23a38a0880dfd87bdf8cd23", + "sha256:d03806036b4f89e3b13b6218fefea8d5312e450935b1a2d55f0524e2ed7c59d9", + "sha256:d1b3031093a366ac767b3feb8bcddb596671b3aaff82d4050f984da0c248b615", + "sha256:d1c3572526997b36f245a96a2b1713bf79ce99b271bbcf084beb6b9b075f29ea", + "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7", + "sha256:f514ef4cd14bb6fb484b4a60203e912cfcb64f2ab139e88c2274511514bf7308" ], "markers": "python_version >= '3.7' and python_full_version not in '3.9.0, 3.9.1'", - "version": "==44.0.1" + "version": "==44.0.2" }, "idna": { "hashes": [ @@ -1581,12 +1585,12 @@ }, "pytest": { "hashes": [ - "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", - "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761" + "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", + "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==8.3.4" + "version": "==8.3.5" }, "requests": { "hashes": [ diff --git a/dbrepo-search-service/init/lib/dbrepo-1.7.0-py3-none-any.whl b/dbrepo-search-service/init/lib/dbrepo-1.7.0-py3-none-any.whl index 08a42f973e93b8acbd66e40d29ef12ad4fe19ffa..385c9e224a31ae8811c03908303ea42fc2374d0a 100644 GIT binary patch delta 5477 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 I>`Fme0HaG*lK=n! delta 5512 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 diff --git a/dbrepo-search-service/init/lib/dbrepo-1.7.0.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.7.0.tar.gz index df984d46425dbda00a0d6d3e2b037a271de0a379..823a773ca48627ae548e2e0448bef1f5a224b3d8 100644 GIT binary patch literal 48573 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 literal 46110 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 diff --git a/dbrepo-search-service/lib/dbrepo-1.7.0-py3-none-any.whl b/dbrepo-search-service/lib/dbrepo-1.7.0-py3-none-any.whl index 08a42f973e93b8acbd66e40d29ef12ad4fe19ffa..385c9e224a31ae8811c03908303ea42fc2374d0a 100644 GIT binary patch delta 5477 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 I>`Fme0HaG*lK=n! delta 5512 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 diff --git a/dbrepo-search-service/lib/dbrepo-1.7.0.tar.gz b/dbrepo-search-service/lib/dbrepo-1.7.0.tar.gz index df984d46425dbda00a0d6d3e2b037a271de0a379..823a773ca48627ae548e2e0448bef1f5a224b3d8 100644 GIT binary patch literal 48573 zcmb2|=HSpTIFiovKP9OswIE;DP|sY?K(8dRh~drNmsPhtCTT?N|0*K!b){fw+oH0a zUdC^Xx2R0Nxpb}T$~#x(>UBC;RJV9Gur^GJ-1jx)`)>V$d2fzQn(48I#j|5l?xxkc zLMK#>jEuJRoLG~4&Fug0OMkvxGul1v``yVk+kQ;`TArO<uK%a+{Pyi-+sgMD+tqGw zIDdlQhkw`qcenq%`IErIRGn~jd;HtnzdJr>Wv6f7ws-gb?Zq2*f4ckW^VRxY+vk~< zm~YEopA|j(zU|##^;`G%*Kd!1oBy)@>a6?ss!KQQ{hF1X{a<v=|G9hD{(ax`*LB_h zgNsvthn4O0e82yK|6A1$|K~QV{J$Uj>3{2o|FXUR-@kdg_t(ecx2{e4TtEBI|1Fgz zMfa>KyS~<M*gpN>|8hQu`wsv1*Kc5-^+5Z{|J~KQH~iZ!w)5Zqz<>Lbe14g<r9HoA z<oCAk>5s6upYb~9x5pm8u`)NbcmK?DC%zmzcJA7>xU{9e6(r>H^6c#FuKB!L_N=OW zcI~@U_hSxrT~`lJ*Iis#mm?E9N8Wt>Z1Ly1kIx>RT6o!NrBt~3^l<Ux=I%dscrERl zz4rC$XRoDeoOpAt_av`Qw=QEi@N=su<Jnab7gs&JKl|@K!wo*iITDsMKIN@BT(ZmU zc<HW~(=T?;GyJr6731ln#k&{t*{$nZwjt;GH|F#EWFHnE{?e;gmRZ_+d*j7TR(DRA zZF#?Q@$Tx!?uXwV<d;6RbMD0hMNJkl>!vfTdCYfwUTwL&#Jk1Gm23?xqHhy&W-NYi z@9P`;74{eXqIw_P<KcPn<(%=tMaAx|EOI6cYpgft&k4B9so=)PH(|kcp3Tl{Jv112 z1Hw!mJ25gY$o+Z8RKeuKow}<Aw%-3<2ww=5;kA>sT+n`C_rU|DF5Zh4e9U0~euu9- z!uZ|}xr2r>mCoWCYDZShDzJ24y=ZEvR9Ak;o6>c!?4sgCmz{5pbW+G^-yhz4z|>03 z$7-7J+7H@?8q#@uj_=uA@M%MQ{gs{K4WYfqtGnCyH~ascb!A)MOn2#(oKY)pFmU?z z*XQ$ZTsrSAa}J;G`extoZ`=39FMk)~z^@!<X2R7_&A7*a-N1L=)6-%LPez|+R4K`s zamwSh)SQP?{=e!A>*cy~H2>bKU3RZO$Uk~=@Lk^q-SZb-I-4ZaGG*k-GcxXA-}YYk zpzz#}N((YQCq!{qy*?n+^3=2=_|}EZRnwk3mR8+X?x{bb$Ch`!ZQ;x<tDdmj_FHbR z6mmexM8@3U*S7=5?j_3AZWp&vs{DCH(Z@@CgZ_0nQ<Yf{nL>B|tNwQP#NzJ;y0zZP z^5Wb7GX;4x<yj@yv0XNNb@|te%6ANLW$%317fj=3S#jv&#wD7ZUGu&iJwGo|sz)ws zos{f?3}rK)2s3AC@hRR1Iuq|PsveMdP?&PS>U+~fJA?1vHp<5BW?r2=+s#1k)#1A5 zRr10<4+Z6fjvQ&9aOse0f_0HZ7NfzdBOBNfDkPpYXMR6>dtc0dsrXe&=B`X{W;9Ll zIV!GF&TQh4c=Vn`aKH_<EwdaOHnke4EEM$(Nnp69UTn}ZZ=uqLGKJ!G9jelY7qZ&c zHyyoFE`QxwM<#mSUxtX94LmL#`=ypMyit~APx`V*^;jdzpKD(VKgmRO#lB%)DZiq< zQnbwVa%=X(kN4i)$v(rNrp+M9pnZ9>T+S@7B}opw5$bKM5@ohOxn~JnUb9~9qJ)>_ zX?8EgH?uFyyuI9&@#-7v+l_IPiswB!KFR;9(&_zKM=q*wXuqQKtZ$Zh(BaK&%hq07 zZfat?NaP4NZ*oFqSUu0{13x`FcC%(VS{0sY+^VO3m(A_T*E4*aovYN8MT3ML6w7qB zi=X=?xT#3-ad5iLKDH~9uKo(<5aISa6~xMJCN@)e(Zh8YTvELC9=By3{H^m~^{qu5 z6JGDWP#V7}x4wjXkFx>)%5s5H!6z*9BDk&ye*D-HrI<eRNbI^T7eqy$oVsFr>GxXJ z6K@!`Hcg$Lbm?A1XmXTj?#4agIg(nDwGj>TxX<k9+FX$Rt+P+gcFpq%pA3swzVXJe zT3uQz5ZJN&0KYi*!~5%>btxU){l)IVegU-y9cA*`-yN5>Tr-)tG(@rf4g0kN*CQ=X z+?m*_w8YscXv%|^?kA7m>bkVGWJ$QGnb1Ne-rF7K7YePF=P$AOYN1f4dF4d;k&jLn zQ)(x9bo7N@Qsy}-e{1eU>raUv`F!3hZ?e<B(zoPP>d$X;o%hIl2tMx+nC;bhVolh2 z#{0__uD^OKtBCXXmu%CVolNShY^<0j+VdsNmHN(bW-aR%7Olmub7UH>{pJ*3nE%&~ z>DSBT?Xuz@&OVY7jm!OMsC;Xsr2WFE*1K{mA9|lXmC+lqgDc9{G;K@jvf@<kB}*16 zo^TLjGMFspUd5=<Zs2v{Lt7ZbjEPU!*Q~!^yCv{?K}>pc+P!wc$LD!3RPC`gnR933 zP5xujw&$DT%{0pR^VlUTon~?W=C_`5P3%g8shNwFU%{>kbNSu32Z(RrXt8=T+u_A4 z&I4x_U0bg1wDH1Qv)HrYduB{|>e8?IXif#U|AlpCj?>kQ?ygTL(+W5%#kS+XfhQbG zx>y)~<p`{mc9vUhR=r@IbMp6R&8|`NSUTQhY`^Yo%iq#)mHpf4|4i<MdmGf<J~A%U z;9fi7Mvsi-qK4-l-?I4HYfa2!+12K5=-K1laP8%6vj?+JXEihH1SwmUiQX?s`1)(# z%bQ!Qs^tpgGcQJLn^ODh(E1;*6WDh5sj4V#u)p9jCCvZoBhe=fHx7wj5<8Hts?Rm& z#UsJxPN#Owy7=bdAMNN9?0&5#Yt>XYyq944eD28gBTrf$#&NPvyR_E!`ge1VM2nt2 zYp1`R^@q>QcDrBm#l5V-`E7K$4huuF(2oH1j>4lhZ0<&ljNe;V%5J;Nsh+OWuKGOL zVV0K3;Z+e+gqEIC=?&Z%v}B>+Izz=zOTvy`Vw|pVZr&2n%hS1{#pS#n1>b1BcERtB zk@k(%lHt?dNv;aK&Ri^0w9P`C$u7hDuG*pgqAfPFghHejZWc7KT%>#@<H7pXDn(av z(gf!nJh^J2rV9tBXLdrQ&1u{1{APlu%TMm+3!f6Z^_;RS<I=l|dpP87OB<{;;}M)W zZQU=e*8=vPjk8qbA5A+_KS^S0?Y*qpO^?+=mR{_0`aO59mE0tO8T{LtOAcLIyuP$w z$8Vy^w$5e0Wfc!UDqCb*zGa@Rb^~kJ)T+&ChbEUY2pnZ!Ub@DLhjUSvw$7BkP{+HW zDc!N$Uze>~<|EL__OM7eIa%C=%cgLe)YUsPs!y45>{#c`rRyOnqqb;r_#E+;Chx2d z9~<2!UW;{Kw)9!NM4iRe)z8JRpItmTG@@oc(;;&`>x=BG?nK%DdUYwn;gpwW!n9}J z*<Q2eshwGPQ&rkn#Y$Ur?TINqUp{A@<yhu6r;**sd4<@))z^Hi+JZlN9bwD;qI=oB z*z5bHZmow|tVcPlY^Nm55;`VuU9n9m<mvN6ALd&b_Y2J2w{9_?#^HCZHEgcWVl@~i zzug^Y+L;>ss%qAB?;C8I5wDJhacK%9Fn&sLY>q2uX15G0e!QTbk0&ieM@P8l!t3g7 zhbGjkUR-n5T$4Y?OIuz3hQPv)T~b~mG8?ybB=;)st5h{RlPA8vI^+Edk(FDO9K|KH zHVLijsg+lAk{7-i{Nmn=GTr6YQXX4PoeU>!-0)X@x$(Kn90xCTGG=(h`aD_7G`sUF zL%zszdpDnJ`&_lUoK`no2`jp`nMt6yCNsFPx1;cd!eZ}pZfi{!JzbXZVPUp@>gkTz z7r%AgiQ_W4T5$8ri3pkW8A`j#{d85c_;+91Q>n<%d3RNZNLZBluSuR$-K@HHq)u5X zw3$Uoc$5FJz8jng(WY0J{?00V+#vEb^U@ms3xUVoK2MLjV&*ZWK3V3vl4<(1XU9&J z#J0||`zBHTWW%cR)z$Nt8=h^M<(iPia@cpnt6Nid_s9Id!@FV9t-Xpri(YREY&-p} z?~JvGGRrJ`roso&vEAlP1(F%TN>)j4n`D<XxTXr-ZS-|-u@}>B(J^{G`Rc_88^gF( zf%ChJZSRG5-Ihzzf4~s2FvOuIrF)j#-O|otwlziB)=nK28y6mX)qUrf0s9N{U@6|J zy*lq1YkxgbKcJE^gWG%2RDp2k^^*;PZC`(%s9V+_u;90Wy2hnUFUJqNneWVV%V0RY zpu8lZAxUe>#m0HJTI$2rsafVbNiFGMICf?Atiqh%DOL}c<({u#|E2yQb&Xgf)7P>y zY&wzmGLl+z8qy~AOuxV##;fkLrq-TiYtx2Bmlg6By;^#)R&wT@(l6PJr{i<C^rU59 zt+<<E8ZET*{jBTx`g!Ym%X?R^KK8Tp^ODq<n3uOdiRbqm`?>zu`Lmys1IlymG5%}0 z7icfj>07gO^-j;jqAqno!Jk$dO6+XWGV0i)(#@I@XTILwe^tZR&%Mun&R+fOr@wl- z`t$3dkKa6b^+MO-X2o5b+_?W<DqogW*4ABm^r5jW<MF0KR^hVZTRV*O^4IC<N2%-N zR&L+WZ_Ul{U%+Z>=Jm$1v>RGIleo{!dCq4meYIGsfPV#dx4_?4neflkH*LT8-BJC} zL$9*j-$!oNZco-Wo;h>Zjda!gHTy2kGD(~Ht!~A^{LY{?C0Vn#m(4djKU<@cH=uq_ z!-EHA4+7`UnaiLYackCU*LNw5jI6s(AK3Wrmsv)<Z1&z&WxH1khOhhd$7jiRE^V$C zm*3yszT|>nLHUdRfZt-9PBSPA)ZCKwkC#7VtNe(0u2IpcUuLB`HcTd4pB>oK{p-WV zZ9JSD&CGumwpPEs_0CvFBOs?zn^9Ea+sj97b237TGQR9&yz^q+w~F&JOLt7Vx+7c0 zyo7VM^3i0sKS#=rq-52EewPR-`hG+;#Ny4q(=64`cina0z5X|!eN#YLyR-1#mKDN1 z0w3mOes`DiR^EJH+Hzr$vy*|U5KB4Zgo@Idg5%TpTbfHcxT@|5s^1DYSF-tc!ezBg z|Cam%Tml{w4)QLljAOLF*5k&W%9P|-6!&JQAXipy;GW&?S8aF2Jf7XU^LB0!_uD(W z^{O3DUY5L>qds5zMXqi456%r%O&3b6#Q2j=<OLl3d(5T$+JS=?CS6cGmhsm62JiQ6 z`g;PFY|l};?Ra+j_NWA#9dRwSslO+_l`}B7x2r#cbED=;0k<Dlr1*}z3+npC-{uXp z+I~Y!QGH!SPmf8;Vix^OtA~1CCoVesPjq8Dq~2pT`EK&R9`1S9tsgF1UT}G9Rl>Rg z-U~guHP;nimKIQ-bZYCNq#bkI=ZU|Y#(CcGL&}Cz7b8;DvrJ!_?~~<DRhGFRVJPq@ zMDugMlxbGh;-*&4A5Z>BJk5%dklC9b6X!JXnLS@2*U4xGnNpoY;$JS<*0?XQS+!S% zXT5gBLajp@i|(<k4BNdS%f{d^^UJF%+NRZ<-}Wo^J_93T_uQHPbl(L<Im}%B-hNG+ z8&{QD%NA+xB&Bs)YwXTWS|>R*`FdpVN2Xg+Q+xm4-sO1BYUWD272*z@3m$1(w3IIB z%+1XgyWVBbR`<^{w`Ee`c?O304PCYJ<|}q=`7qf_&o6amUc;$?<kZdGSI#UHIaZYY z^%|FRSVnt@)1&00p$vU8*H1Ku2Zp(n+qr(=ZsKf7U;VeD(Q@beRd<XRPCop_>idr5 zvquE-)b`0Ae%}0X-UBv^<lSrJSL{%jv@Xrq_2lwZ>@8BFIt!BYuKyRFJ>eUN5tCT_ zp<2DG6}JV`G&Z`q26`R6xTfy=v^}Y5M^e=}Z}O<@^yjh^RlFe0U=*skXkq$GIi+Vg zuHS>)KByi%EWozbVH%s=@?W~5`A*TNHz_H2D5-B{%V2AJcBi-DfrBc;#s^1~f46K` zxpMvQlO0*7Km1Dlci!lK@y!1_|I|qSw4ZMOzr}A#ck8qNZxo*%{bXPMef#!lKkd7J z%!zEgY06ye{35G;!J4;g<}^Pl&oIbcv%=g(MSJZ<2HWNB$3DK+uE>q)Ypxb&e&O)` z+cE9@yNz2LXT4Hf8MW`i);IIwx!wA=J-u?q?<|j*VaeemzVrMHm{?OMTi<T6GYgjz zQLW0D(>RSw>Z<jTJrz3|Hy-%woE%yoZn`eNr~JaVRUhM-tKt^l{FT4=`2KYqTc2E* zG3Sd(?WfCcJOf-OFHEuAyKv{E#h0Xd)V-HZ)ikg4di#FrB$uiD@9%hqR+StsIT<>$ zVd|uurQ346y?0HTA2ezGl?-psLtM`GULMD~64v!B(YgBI&dJC~732I(VG_@cV=sk? z*{G@&x;hs=^LrNbF=q0lU7Om>$|p@vl2BEt&SaD;R<C^-Q(p8bT&(Jp2ixTNlO`Q< z+Gko`G~<uYY?W!PYcEYY_GI~<Cx%CbPWdQJo?kTiq>^B`s_IltyTG)fnd`JgJd92+ znzeKCxe|+0o_4{y(<Zenn-HI7G)wGoSX59{-zW3pqFH~YOkW~4b57But4{Nx(k{)? zYx44nn>_#0q#KhIFMd|tta)|olqK6bb&}tym~ZVl<yCfBtoq`T?OOt;&14bRdmVIX zZAea`WM;T$ZrZaa7NX&CVUy<kIWtFRy4l91s^@DtH%Fxf&HXcFT8wz-M194Res$0M zw}HI!?n_UT(WLiI(q;ElY_|S7?Ro6-<6oyePF=n=+uG8<?v&@H%SCKms;`%BT(oJ@ zccq%5cPe&E4W>;zBc3&Xr)RBX)v-OEb;hc{Qx68keY(HJvmsJo>NJsvtfGWS&!(kn z+<tyiXPk;GJzM-I_(T*1C7wLls;VwIZC*}9)}_RsC)<~*DNdW;6Ok2^wDV-=QgzK~ zbJj!@U3&E7$x)tTVNphlg+4x2G0j@{+-Q>Y*JsasimvQEyHv&6?QX5`WVy>~o35yw zxDX!}WV9r0;?zkZGxLi4=gVl?KUMX76&&fdDdk9t&J2^8Zt_dj0=2G1MHww!_IT>F z5Xn!kcTU#6Y!KzQX=zl}XSG<h7}3q@@mj{4rl|NVoi}ZI&&o{MV)fKh{+TCdX1SgA zx)kzg*_@QKCQ*92mBE({ygeR;%sVz|lBMW<EzOm|b*H@FUCG&5G|9#}cIlLq^BwJ( z|Cacly>46oDc!^<cb`gtsHUa2QN}GUZGB6VjW_N6CuOKuEN@8(JnN>VnrX7@tX2J| z728fncnPgk>wM;?##^5A+)wN34G+(gOK&-(`y2U2OH_I;&wQHh>vVQQowuh~=rdo= zlPhNxTGmfmbx!-4U)a@T<7Ylmp~osLPp&@IZ|5(xI?6a$W%Dw@t0E`YW?uF7D4ROp zXj0tcxJ8~P*GrzxnU!*5i<*~LpKrze=bn>vPx^GJoId66>A87f)2!(>yNh1#+|jzd zu(-4<r!--slv#0@?~=WbSLoMlbK^H_pYlgIdw1u-n7SJ;=E{CKd;8Xhds}wT^HgEe zTC&}-()}67^DB2=+{;T?ZFg*bpLum`v9pElpR>KbT>PIG@7?0!Qy#f@&7YiJ$7Ln8 zGjE32w#||V$&Oj6rR{z~xX}AzbJBv(U+yYyyepPa^hCP7{n)&XiF>v&83%p2CCgMP zqjW{7EOtH5dCOWZpVuCy5+CNK^Ran&ET6P(!Il#{oAP&Wef!p9YPaI8$cTlmjwKN< zn8Y|Qh_`7b&sh)`Gs$RbR+7%<=Sg40{)qATIqFPau&!d~Z)u*R3qM}Bax9cN)!wUI zb~`7gzx|pb=T_e@wxx|nPnoRgH9zo~f#I29;_BlYPVjdwkEna_f9t;B+jsl+%ifYd zdt`H=_*~(+KZ<8eduS0TF>TSy^)mgATsP)A3o=Rl+c!NjM_ar8q(@2g&KI3LeSY`T z-dpZfSodMx>zWm3wr%*9wR?5~-%N>Z4k|l@f^?6sm~^TC)P~lg{^b4P47<Jy6((Lk z{PDuFrv^`+Zr1Eh5Pz?FtLW5erI2|SW(Lo=m%ncPf@2@#o@=g8tk~PRebt|*`VI^1 zZd{dc+O_G^?fm@<zcRl1cj~{<jH43L%rm|!vR+;ARli7h;geHbJAE4?>>s@nSn=^` ziDKqI_VSP4C*J+p@p9h5Q>XmH6dv8<IKIa?MT)W7xYkkOSpEs-dk2KJ)LE<SkeDT^ zb<W_*I)>@)K1?!6sV)9tVJwALwzi8#v^$GmS@>&}3$OXs*v(dgT#>QtpPU1H56fTJ zAQ&dkYU1^?J~6|wpnqBSbGu*Kcjdkumc90F%>v)WnaOjzRF-VJyLSJoPZl44f6JR1 zvgw!DiIm^`tNHft-ur8-`KD{(9_gz~sySHe?6z9#6?nuxXNl%%Z@;G?{qIVa>EnZM z`gQu|70B-PUbuXQJ5z6t<gss#x%JNzeosx@voXWSeY@M!PdU}xA`kxm{(m=@@8A3X zr_V}Q-(KJ;dF<LZMKzw{{`~Xz9F1=Wn{J+c^~|}Dvoa|r%)EQ=tNxLm-}6@1!K>b+ z;19pgY~N)Zv&<cqX=my<`8MUSoK^f<D(;pT8scOd()N0_?e*BT%bu;|b4*%Lux9<e zS#klYfwwk92cK@{So5#acfyHV3!QSWMg*5I^<RI~5w|)m?btfSz(iR?(d^JU-S*dy zPRQ=*S(MUeRVK}TtISsG?mNXNrAzW>X(tHkK9f^mxF4ZrnELp><E-BYkEvFD)(FZ- zJ#4YKpyZGY1Amyg+Y`yD-($BwK7Z;nzuDP^dw)*nllalNwb3`fqwV_j(CHUu%Pg`l zuUD3jy5r#c_24$S(CeF+*G6B}tdwwY{8!Gv^0~Q1eC3&m?z^5pRd#zDt@?1r%QWXL zp0cum&sVJFUVhyxqxjI~qF=6CU!Mz9z9Vrf_SK)3a`A=U0%umROuH-_VQk^Uwe@-6 zA`Q-?vTOP3h1Kuhe-dQ3wn=%S66Y;{=EJ8CY)e)*Z?%?q7m#b#{E>gF*~B&*X=eQ! zaa-rG-!7I7%9D3kyR`4fKea#Uod2ulZ{w<7Z1>LRf}S2*kCb-3G-EPL@rygWYof3J zeG%-Ue@<ZcwuZ?<9~)QvTgz7aS1l>p;pvOrYCHG6ZLoZE>Z<4KU3YinZ1X?YudhGr z`Sr<>NfFPNl@^uWv#?IQCSkWfXG_$3y>)#vW!uh2tGk<r2S^=#{>tm|oA=Yd{CMlS z+5?oIj*3pXZ(p%>v2D*mA+f$gi{|~mv}f18%sE}>b_O%PI{Wmc>*F03ZXI*noR7R! zW3^jnba=@Ej~RR$PTzb~{{Eed9CtwLEtlrwZt`bkLt@w7iaq;-*I#mG;9?<vmw4?* z`md~)f4KTd>$T~NKO(<ZpO}8*?k}zreIbdQ=bbqVSes>LI6wKMdugqw@>5sA29Aix zpZ7DSea$-dyX~@T{+dG8LuWo6Ix5w$Q|hSvCQ*aQ<@Gi<el0AM=lS*eKWo*i_@gUD z|8MQIUvT%a+Ll%FIe`n#&Xtebd+X-OoRZ4_zd!w1{`Bwr)BX!T&tK;!bv#{tt7G}Z z=k~d>Z}xcI`TsAg^55koJMZ_`F74j>B~N#6G<IfuOL=zYKK=9c@xT7hd+_J`+owO@ z-(U3Ke?^4<#((i|->3ilpK<p1xq5qx8^6xoi2wC}AMd~Ycm7uz{<gQzd8_lieqZ6g z`x1ZbQXVffld=E%@BF`i_Zn~gzj^;w<JbBPySLu?A9=$4#_V<L?`)BX(%ttv`RkAP zx)&#>9?LwkidA{nF;1N+=M}mhEtP!{^Ki>t;q%3NMN_Zbo3-z5V!lsn@RV2C_rrbm zH}hoPHQ%@Xg5qiE+txqk=H%2BH0)=u2zVenC3^Lyzp>ZfJ}lY3TE4;4dd1-#S#=jm z-4Fias+wVVR#T<Q?tM<_)Z+aHn%Xt$MT@G|EthAJwzTTle)&RRqKV$@Dc^;vPG+<1 zn)BgIC*!h}n~!(i^_es4tNoRi&AH2}XRdmac;L|`&U3NO+tsIwpL%&P^3#)ZNzbRM z`UfZUOUXG4Fddw`N^!~W?LXM|I<HE*Q}xdMboTw-5<dPKlO7*+H+}46aq)$jVDXjq zpw+e8lfQlZnx(r`(<N|?X3dmaBER}pY34HAs7Onfig*;tS8=Faq|rA|?ugXn{;h3a zqKd2)?PNY$#CZoru`D<6b-QaZ{dkV+gp|qM>=PI4@8+`$vzPIB<I1u6Tav5F9;vrx za<O;w!fRIF_l^wGR9L?<Gw$>{0eSbblUoAUehgW<b-vlTDM^`&<IK(edBq?4%vX5D zG`A<<(%0;y$_4)GHi>;~Vp6~4wSM_F=QRq;Wxw>by-j$zL3a1_SpV{lb!!*PO9}HV ze%yI@k+M1evW(lSELXo5&$oG+DPmvr>J!7nxJO$H;`Q57EjRDf5VL!_b(K=f*9p%u z@88*<KFQo>`ldg(<<}YtdQZJku{Zm%p`gP17ak`p5|>Sw6!WBH1?TsM<0~KKvF6Tx z^l@fimcf&we_|XG8ASe^GRaGvTPwm|YE=`pVb|sG!bKckPV{VP%ldeTgJ-&ur)a$_ zpIEns$4vgT4Hti$_?XdtB8GY9yl&^}#h2CNTuz=g{%A5)WbUF%(Y48!WHlOm3cI%Y zC_a9&ZbOq-cr34{`{dTrOAT4>T&t(Qie>HGCYR0?Iw|<;52^KH`%`-Cf1O&9uDfJq z^wqNMuS^WyI=<bMf9qV}j|D<A=dAoa>z(k-_g@S2oT{c3e~g+?WuZQ`;Lw&XhY5XG zk1I?p@a$-x>SB1!?sm~u@2YjD^(QWkzrK$-zijtoE3G42-(?tl$&9uuWia)+*S>H1 zzxhl5r@#CkS+|ep|M{Em9XB}qKY#Dq!PPDQ)6?@`{;w4Kf1YK2Ki9L}<=M;&CePxq zJiwgy@cH$p!d&7`m()e}X}=M+`u+Rs*X>V)gC5VlufAl~sV|(l|34hgGre8DSZc<p za^bS*b?@04YhTvQ6j*rvb>cxwjl+i*-8%VsgU=_I6>iTyxwI^p^0@QIu0Oo-O@|#= zZ%yP8nOOGmI@hajA2#y7u}q6QuJfQGweh*vrTY^KOeNT(J73jam))i*tHL>5Wlcxu z?Bok>Q6=sAw-&_KP5bu$(!cp<|NT$Q&whUV?$W>idvE_w{P2V6&HuY^-`>5O+x7pp z)eXBF_iwBJuK#`Y(!clxf8~weFMh}HGdAtore6I|KaW^X)l!e^S`zhB>O5mk$yvo2 z(*ng0@;;4qxvcmlowMG_++^PWa>n$-qVnRovO8nDP4;U&yE~`mP;}SP{B0%ocihu` z`lDlcdYb%Hr`6io2X81{{b#pnPa*f3w43ivE@v>^Z8v|nM5c`^^V+0-W@Cm7sZaBM zuPQvMA*LEtW0v|Qd<XZTb(1al*eWcis2}gw41ZkqV4EfLt5&Nhr@qN0TQXi6xytI! zU~5VH?Q-7h&T=IiU13}8&Mm7iaP^2zC{r>KEeWzQxRcx`pC-lM!!l{DRwwIMi@U7K z=NR@GGrztlbNX{Y_~uy6Rd-j$Xs!yIrtNy=)7o<<n&;gMJU7QxJmzb{CY@dV{vQ=e z<rw2)92W951Xdc(+;snlD?^Fj_ph1Ro3C2&u9Z41%<h%!ru3mt>iNr$r3x9zxe0d4 zGdikHmhzVFPgJ^-ALt%n!CLJ4V1sz0Vd3jte^=T%6k1$6V)DGI@!5yBOGLU4`g?wt zlvCKcYtp_+M}nC9l)J^h-&VQy*r#r`OIym3{K>*gg}oQfk(hsY#pz}T(~$O^u2<Ii za-9y${UjdhVDxTXsr9baF0Z~`n{Xm$bN>IthgW?nwrUk8O=Q=;^ugX;?W4c$%YU2y zu<=(mZmZqjFDlSxf88WM{P#uWld5-O5Bz&~cio4Q-aY$%xcMBiH@O%7;rTCi&$<su zJyFhc>+eps<bHa=cAD=Z1uv^G>6@)em(9;)M?|>J7y9bO7BYF((S>#&6Pu^3kM=B& zyO{bi^WN&OtUK2;%r{tZFDmDe-Qmyn*Nrq5Z&zFX#JK)vFgI(r_)^Zt&y={Em+Q~| z_4w_Hm;cVhC$0UcBAV~(_bUD0By)z7d+f5a)vxVdu<_Ad?L~id_WhkH?W2Bsy|7^T zwc^`lF`;rTX)-Ujm~3L4%KGY4bS}fIqW!)19M;AwW&1ijwaN(2wAowD_~Z9gwz-FL z|2vlK?#kZ1{nsrc+kkX?_glY;O~oZ;XFfdt{mRa=?VBr4zkMK~6yY!3z*0QRk>iQT zmyco%vqVaoD}zt?E1&%@*)_lF>AW@5OLGh6iT2p2KZ$tc-8wyg?tg*ewTJ(&z7j6` zf8w59>jeKl$uKBUxX#L`$rmGDulju5=lQEPvAyV5W0QLyTbv*))p>tW*T?@)a`PT& z+I^a*6Xw1(m(#8ByjF&Vw#iG!kGkzWsm|;iU&E3oZ<3muX2?C!Nc*GOxw{t{7*71l zH8t!G{K|jc{t#DP$BN($zW47R*nE9n?pM1d$=!a@Osz9tEmPu}{V@7t#<d?tdN!g< z&0o1|Ey(#a`P)~;d&l4I_J~QDHF4Vm*SzqyeGEs~SN=GjIOS01`BVmjYbG%T`Ad#6 z*iAjB;87*|VbdxNt3xcQS7-T~n{KgYFwpY1j*h+<dGv){M*LLwP3xBUt$cQ6#gPsB z<C-7djNKq{tA@#ib@o-YsVdb>l?PazcHZ0kG0uLzN}H5L6EBlWu1UR@SM2N^A=TLi zIg5)ve%^IYEbg*E;K`0t4$M9Qk~Z2dsS($Iym%n$`KT;%hQ{PF#ixdbKV3R__b@0O zX`Z!DLMdc&u$<r{6B}*8U#IjAtk0dz%e=@Vro=MEL$u;nW&Z5C+jnC$HyTWueAabu zKkF@{(ooHtaaWFezV#H8jMK?U>};~B_`KQS&wTw-MFm-oy`ht8d+rtgx_kSUukqeR zmnWT@%g;Go?VfFV>2<De+ooTOF1hrn>h(@#_xIUag`Z-$D@|0wrfi&ca<6)fe`x8% zX+Lgmwzc=DShgVK)a8(ZvvKF&-QE(h$hTo{o_h0?DGL7SI_4%q`z4AwV^^4joJ?9U zrR?D9<K`b*#s3>_+SR#0vT@1l4YOSNBHH`T#Jqj%TDIX?*zRTD1^-`a=G}MUdU*aJ z_D(*hGpp^ctWA4jGsVXJYo_IuHB)oEXPag999IdL`pmNLz{Iev?AsjcZC2)`Z2S7^ z7WdmfyXQ<}seF+e6C-QdZ=7{rHE5BwUst;K<3AJE#UG!X`g57>u8O|7U-g6Mol(}3 zyy>qwyG_~GEY$S4>|DNRh3}qLGBYI=j<2|owC3`DMefz7^`)d&ug>4B8hP?);Pm)a zR+-ngzHd5w_2vDqO-2>za*{qZ#e9x?rm9IT&Q?~sJ|m<h#k*_1y5PU4`M2^;Fnwt_ zk+AZ2<kdzGZ~p}XZzQH3yLj>B)2}B#ru>yVIx*AQv;Nq`n!qD>c%o05Y8_5GpC73e zu}|W&k(u(+n=>A+v01)w<pKezRlj5nEk*f0z3~eTz0Pm^=3JzQv9n71UAxwpd7azL z?O$iqY-C$9>#AkT^(}v7*d)%~c(W~b&CKV~_OE`tlaQYt{!%RQ@v7cCOBZ?B+6zx# zP-AFgV<o+GV}YrveiPH}l3g_(?b~?ty3aoql+CxF`Dw=-zpBDhznM7rw?BTi)W$Jv zNAc2E9l3U0L6LvAIPQp#{eP*`BZKkQUhaiL3gUtD_ymHymhlNZb6P2v;w2L6IpOij zX{q~|VjcNXKW}d96kn}*VrBf6-I0&d3iY06^c(M<dpK=gy6@+w(jQaT#vIqIvRk7$ zpTGU3i;~3Vzor5A-rtF4HeMUW*r)jJ#f6z|Z&PjxK0IuaC-lo#bAiK-nTKVsM|^zo zV7+qBLBCxKOphc)zFj1;cCpk)cE0<(42-W>+27oYdQ`XS-wlE3u}j?4Un_146iC|P z*WSXt()W4Df~3^6=KMUqzpPgE-QN8Xt6Ug6G;$fQDTa8OO`peMxG?l>gr;DZg5LDg zE{o^Y8ZIpSE@r5h&$3b0Z^eRGw&elw`T@Z*yXrjUik{_6`W+bOId|?gtLH0U+naog z4!@sfKSAf5{;QAduC|YFpI>3*^I9T(;qsIBSS^nW|J8Gd^!y@ewA|#V>h|~Ymw)wb z-0<gI^~Z22Yv(=z&IT>EYjrijZ3n&5TU{4!uGyn<`rG3>hNsqcG3}Vm{6NQJ^V}SV zu8et|a`PO%-!ap24_EK)oGs(T*t>hWDR0Q!t4wS16YfPWRI>W=hF#+F+^f0nLM2N1 zN|u(EJwf&lTa^{u${yX2s*=!;Jo33V_3p#JMR6{<OSuK-^39X%5<hrRHQm!x?0C## z>x&j5N(XLVnUZvI;;D_R1p7XgiAbzt?wXZvx8RbD$HLhirY@^?EVW&)*BPjBT(WuV zjBBsir-Y_O#>QVsWZ1Rp@`HQD?&aSf9a_Kc_D_zhdnO)cw&XcuoxJ#W^t`Nfg&JH@ zeWE=5fn3~=HeWfUc=X7Y@|t<e4llnHvL!E~#a!y}hgWa5Ez+#NnY&WvfJ^kNBkF67 zo^8CR#6Epi^c$O%E^B)4o;xfT_rmPW>|_Qv0j}eZEgW{(Zl1jE#pkW-6T<$qo&7WI zTDsbs&0oGpPv0N7dVk{aJx-f+dJAG}ZZC7w@tqyzapS^~=nj!Hc5AXPJX~SA|C{TZ z|I^ma(4Mz0`&kK>p}e`uOz+sbnU515i0ljYuMG3!*D_aoI@4ln<+91Mwzfn*Gb#NT ze)8<DAHScZxk^?~GrlEytL||UZ}*M5mq|L@YcFr|?Up#Lb+39-<Jo13_HWM>28u?u zuxtOXe{uHojaJVc8LK7jZZMq-m%O<8w`cM{7vJ71G8-j-o4A&hiaiOd72J0@|B~aX zwCYKhHkD-fiGP{BFM5aMr4PkN80YVd-EIC)^+{Bw+?h`{6RqPXs0SUHwanm}tNWW} zO&fOXxO?W^@(W7KKC`S-aV;`j5!W_-gG9@sD>{6Kr$!bSPn{;h+j{PD#hv39jAw+D z33c`xXP8_$tTbijo)Y!rRVfbBq7DXWS5&QS@K|fps-X5>KjZAJySo<rSo$Nb>wSK7 z&2)xO;Y#Nt*Xs*8M=4ylP_im;`&qJxU3$sNP5b9NZAyQ-rK{w|(lvU4VV70(T!Nl| z{~}WqCG=5EusoBg`kKJ^97mh02?e$5mYUgquUIA<>}ad(dc9)Vl(?<GW=yo3y-9I* zJ)5iZ`(LRVl0u87zm)fI+RhQ{^v!Ci+`-1znu$(F7>#8aqZk4X@=oB<Pdom$pUr6b zJKKD=_~h&EUmiJ!&hg}(#L{2iB@%Gn_}06qy5pPMKQf1Vyk4lbEVNSW*)9+MdEy`K z*HqRfSDT+KX`G<3?&`^>UlvI05_wpd`zvrwTFaUYwZrT$b$#sSsy<l!{dq|ITm6V? zU;bH%%E_l1W-e7a^F@5-^32eOD@`9vQf}&Se0|Yjb8hNciHOCzFL!<0t7YjL`=_^K z`L1t&PcF`LV%+v)gY=?a*Y-Ode&XVJi%WM*V358jzu6|Kq_bhxa-MVIcm1!eEY176 zr0^$a$Cu|??TPCS)LcAj+$NK_%G~kcbIX?=)_l|dv|QF^`WrW`a!$^t1>FuYuEw7B zm6={gKQHO=*R`JiU4^fAjhgJ?K&|-W%*iu0h#k86^_>Xg+2R|$Id6XUb)49K@nvpH z_XVHlb43@fyv;dzTFl?3ujjJww=K|o{G2=4k>|7bGyB=|Rj0+jkrZ?3@3uRTR9Ka= zXZOthbrn{+OBoh7p4_PRi+S=Mwcp!%lCwUf7S7hcx;My1GxMcLqSw6pnnu#ePg70) zt3C9)Wf|e0{MPsc_qK0~=jt_ht6SG>@?G~PFaDTcn3&I_pL<SzxcF@T=RNU?m%HX} zvGSbs(~^B{n%ZRV7?;awhP`{VrJnu{W6sx+SoF%Yvi9teGll1+cJPO7m+}?8p1s5Q z@x3qa>yvj@=eO#pM&6PxxVa=^UP;$wbJfE65iU~;w!EFLJy~r2kC|^O3OB86xm-C} z*Y<nm>oqQn!8|efF=sZcklOdRU6r5Z=Dk}=|Ni{b-9GWL2(ND0MS0mYh6R-emmTQg z=5DrV{O@wjZH+{K%eEix&Cz_?7ZN<I`x)8(gl@Qyv~TkCTyLAk>1n|ip8a>cw4(l4 z{r^8nb50cTo_p#zFHAy1e@)Ca?#XPLw)&S^W#5)+Ri|2YD=a<Exr}SAz|uwM(lnNQ z`Bmdr)-!MJ9`o<qQ)X>2eIC4E&;An(Klc^P3qBtIR`BdbhUenvG@ZR>c88yP(xYZI z<Fcggt%`fBGgs<AI(_1mOUd)x%D_)v6ICUb?K<;zLYPC*laxg#Pe>j6uAg@Mb$0^m z?D?!s@oRpyxa@pUtAFI=qiuT+-Fuc~a=yktBQebQuBC$)OO0fYru79Io|n&@PrPIb zUFY#i-sd#W$0wF+yBa=TDVzT1v*pk9i&IMd)*KKG(EM8QwpH%nUSs~p^UX8LkA-Y% z{rKOdzBq>WXNu8+4XcBeI6w7b(v|M=yJ`1i@veT|3CU*1dygMI?Dg@rbyo*ZX(79D z?(><(Qv|wPL>p&imu__mf9QVAf9>`?uNQxamACr0|7Fgi$^MM<9^K0C{d+*lMOt#f z10ku&XC@1Za5`^WuqJt@a($)5xtyrBS;`AFUEUd8uJDQdEq98ozNDLb**W1$e0R+3 zSGJ_vtO$Fllkj!XvXa$O^1-}kx$5@(n{sc-CgJ%Wrk6g=%U~%z=F}NJ$>x8lO6m(I zV>N?~Q5$dkS=#zCzVqL*lX15^Wn;Ol&%O)#5Po|h=hUQnwUqO7uN)EByW+OnBZY^( zf~j|nKc&1Xx|pLT7-2fMdz(i?XyV?oiFvoy+qbP;A*cFy+O(=GN{1(=mtCvb*%;3~ z_0B{)aq)LsJx<ELG*a7n)H>=CH&=U|=O-)XB|%S0m%M%6cSM=3sb}efu;T*x(}f%> zqCd{CDP8tJnm^WMrnJn%$VPqlEywkn78S-#KKZ);7o*(<*=gJ|Tc*ESeDhT2S8ubH z_eP8U7Hv1lsEA+O-_9OBDUOLncg8W1E>BG<XB(DRt?xbrtemi1VDGOB$A0r$dCOiB z&9hNnvG%f;%c-mKZZoyFhaBEnuxsimDYK2o_9WNZZdcj1`&f>vw&h*6y3j3A&+RwM z9a!O~ppq8$y7JwEw~?~fU;mmqqx~_bv&_|^_>79h*IqX{NhjN$tABAy<*E8LO(VXT z3Z2*KWsyGei7O8-*xbWZb-^Wf!S*mGon>tIFSjO(c!{658kDq?X=j$#vdbnL*gM`F zobc?>q4}miUF{tTv_#$KMg;pDuY9!Ux%l#DM;`JmSGc1iBEDVe=Hn?MHbL)KU!5d2 z-}z&b=qwkxqth2%Vi4)N(*1qaDu?D*)*Is2x9`_legFTikAD*$|9<!Ndp`eud+R^@ zzMjAOb*Y@_G7+7aiI;ZAW=uNav+BwlNhSS=#*2(K^BRKwhCE%lMWQiux3JF*?aUyn z#T~m#5+3NsynWDk@>oWT#s$YK#pkS+r%$pDviPIielY6ArfJ82T)TSp#;TZ^LHAY! z-23zLX!eWzEANFe6*`#rBwT;BPXB6y<yD4xZ`3a{KI3~7U?_EcapL@BKaIN7V+x(i z?`R~3*tKu)ep$)*NpJD>Nv?74{<3H)_-L{{pHisFV3RDsu=%KDYHWYbtANNkDqmOV z+cX}nU+_!9w(Xay&8wR#f1e4px;_5&>&c&8m4$NO{CT>6v;Nu0a*HAM+NTM7e@=UR zn{mspe3?lr51LB+Y%J{m?XD7IP!KlHM*sUv%^6~|jeP8jUU?@}c}<R-(;&9F&^PJQ zOD3OJFM|%$=`wA*yj{1b`z}x6yuKI9#WuIU?pU<v^`eYi7gp^qv1`x8ug$i(eqN~J zq|cH|<<=&`rIrajrbo95?1-yfyQ^*EjJ$-a*TWvZ-kW+zOZQgro6Fl}H?ZpDE8I!` zy7hnIwQKQl7g`?_onPp!QXSW#H}T%<?MuB?3O~$Y<XV>e?YP}*!GjeNmTI=^v_p7L zOY&M|yZw0eGtj!=_oeUhA0H%l^S(OxEj`2_AXdOZ%Is3tai{ZNHG7+XeP6xh$wTV} zT#+VWNf*y=_Ez>5e?5!iT1x&Jg?{T<xrdymt8+>Iv-J#{u&P}7^!JY@7UB$F<#Mgq zXU}KK*_Ca(RNPHflP^zRs@y82bM>o>e%jyWKCa3*^8JPD-`<<w*M4Ps_j}#ZKY=mt zPe??qP`7thUf_AWTS+v1g03lx=$2C=ca|+Uw_N=0!o@b5nzXYw2~Mc`^t#G4%#G7a zgJqG?M>+NSUQMH~vXibx?TBz*VYg(pSklp4t!*2&1@M2530HsZlis+Kf0AeG>CCiD zyR|XCuXl-`{U&})O3wA=!)s@94r#AlJY8Y0UDRWngRY-mq-Xy*vMA%lP3DpfOeU94 z%sMF}b>x71O2Q$=)nAiK7&MgLs(#j+UwK{p_%Zbli7FrTTUfJSzuCD%Kk0Sl4E^tO z4pv7uec!fE>)z=)wl@MFlFR>O>icA_ob@s%vVhNS<IE}XyOY0Zo;)UWJ#gQawL9)i zm?;n(Z*g2t^L)l8=XXofrJi;#^x3<s<F%g3G<Cb|?DTcsX@^Yz@aWj@TO)Sv=VS&A zOaF%-?j6eia;|NSO?r5zqu$L2$38V(S-sP^Wz+5&znNO+TxYBIEY&KRz@(^a{!sS0 zj@AAb4PwXczWJ!L@ts8X4cS?dQTYn~R^NjTRlHk#E5@hfgG+RU$)Bfo_a?u2Y$#}( zyx>emmxW~9{=_Xj`hTtdeP%M>ePm+t`3*OxUi$p#TxRvTv+G0z#CG4D%5;Ex$MlS< zk5Lgzx=w%JCou8Xp_Ds8ReN_x|5!FPUf6$MN2fuY{?zF@+rMOA71Q1xR2BE3wf6q1 zJ6;D5p5AeuGqG`<n_oakiKy=mmd%+?t5i#Wv#P{Qn|xoRNN4Nh;GIkJ&2JZ0Y8+`Q z)`(B|rqq^d=le_P!+eAAiHq%PZQ8bM`qtm8{KO{Pf9mcNHE$)KRBw9hDic5R*2~NC zY!ly<Cq8$4@=D5chuG>YmEZOER@Zl}kmyuaTOK4A_at(%=A!t<KVP*OPCGB0_c36F zX6rj~-Bj`VYe9?dx1PMwI)D3=7vEGpZ`|Zh)N(zb_oQd3=cmw*ER&bG-&;GKSF3Tm z^s|^G*Hkf$5aTCH8<>+XO*3~C73J*NGQFz#-bRM0Ck;$jEN}b#x8(RPjYG*Ux^Hr( zU#UyqnWVXOW4f*EQi<P;Qp|3vEd?gBXZ~3sP(4Xpjq}_Cu_xX)KL0tjuSuSJmD=Mt zC#kTW+Np;h?R(H&AJZ=wR-m7A@5cF~M{D<aY;IVY^?9?x4g2|zTtwqK_rz&?>@WS3 zUMtuc@sx9d<oku58}1*C^ZYEMq_h6@%55LKx?RsUWo&x%|4ZZY$%(IBSZ2PJ_#B}m zxp!|v$7R-4Y%*Jqy_8{EJHs=5(}T!WT;8FHE48Mq*77MW{b0UKv*(b+kLMReHtmX! zsd>eHNo12k73Zu&DK}g?gG^f2+>3Mg@J45r)4}W)aU0w=h}`i$xVPZo-=}fP-(wz` ztp0tp_3S={!da{ry#<y}P83%45?mg+*Y>gEx<jh^dH2r=EqYXRfB)n8$*bA#@Gs9e zwmaNwSJl%NrOcPtZd|+XpW5SI^8DkyPd@~%ojdV)!um-EcA75?O8BCCnV;dig4)qH z%ecQvbtTM=P72_gck;5K?3pT&>+=tY1lLvwE66XOt$rm}IKhGC`)kw3YkSq@Z^{bx z9??~JW9FR^SgqQ)#_}qsVRNEFQMhk%r1{Z5+rCCymLL7IZSJKYomo~ro~<)$_H4KQ zzVL<W;<J1jkJvxVymh?Zvnzo2Z)uQ>Sp1oPSFM6vj?^V??U}(Sr>eYl#)NGXj;t+M z&{#9k%I(5jhE2zq3q0S<znxg8GE2Dn1xN4Zhy87HQhIhK^;c{?5x(rq%21svhPDZd z7p?ud>zl2JGgD!yTdZ|~YBvA!$gNrY2@6+?n~JUqSS)Uu5mxZ;>r-9pmxZrfMe>jR zmx<0&vRU`9QZzRBaKhIM5v@|Sv-=J2xlF(IYW_xvADVrxX$<MRA1-)*@9x9IMLP-{ zu0HhLw{D4(Ql+)f2UWJubzkMB&%S%b9?M*>S<cb<R#5KnqVKO#)_31tbh&ztnpwf` z(5QODl@qQfu39tWmDsDdJTk{!yyOIgQ%*PKwf8WZ9yD5%dbGWt!_D|M+k!XmB+v4T zIP<vG$?eeyzIXRZ__a1sDS?&8oVT_6i_E`%bUClr<;qjLcYVwh{bU(+>cVDLrhV6T z%Q*A)yiE7{|9tw&vs{(@uRndBZ@j{H_WY|#oy)b)EGtX8{=c#Izx<k*|2_Zz{d^y> z{Ga6izs27!`!1cQ_OI^dbPX=`gNyV7uk4NuSdhEtwE8}m!1wP~KCRia|M_W)3n_nE z=ImRs<ox+p+O8d!`LDn1w{$)%9>eQ8>wgN<Kk4r#wa!c%L?XZEE_rr0Q_lXyb4ix| z7v&2lxxX$}T;%@cyU3<=)ogBqi@!rAd3en%S!mR&qWIpWOi8*~V_j5*U|T}l9E}+a z{|^1En)Nx}M02yz;m5AF*&HrT)@C2>$+8~47!=|od1B**E4ESD#WII&b;Xx!^NGE% z^ZjBTn)LM`&$`nd{fhtPs@^r<eVWmv`2OL_qfRV;O@vgLXD#2DqBPfbzT{!)uRA#} zFL%&=-}%k{3Aa?n@&zk26>X&!9%9M8__149);l`k+1o>{Mx{Q>GfU1UGB9LJ*%voi zW}mGLbHusH##N3dx*va;$TvSAu)l1Zz&@>{=6UUFyN;}1S@LrgBlm&!laH(&)K`Af z-LuJY<uc~WzctqTPG-L<B`T~R^O{*j?kMA${SVG6Sbq6ox<Km;+k&^>4cGC!Up0X} z_rukKrq6{oJDC^1ohj?RU(qDzNxhIUPjLT<W;Nv<liiK_8=N<A%W<k~KVHc@J73{d z?XC~2e$+C0SFiZfV=`-ES43Uu$L}XEUwUS`IL*gJ*eG%1%k)K;kE+hil(ox!;k{-5 zmDDq?^GvdRO8#H*a^151`595+i*FNTtsC!dPJEd@FU)u6Ro~DLvo0-Twtf+PsHW=t z!Q3dpnxBgL7xFBWo<z-i(Q=@0?;5uLA79(G!k>KD_w9y}ZCCEe*DJGs%AQ|V(Y@wc z|6wKhCu?6?>V8YGjF`D#-@@&yWSJLiO<+s;82m4C$^3mU@APWydm2&`-0L>g?rVho z*I?V8Ic9MSqGb=q7O%N4CGYzGKxxzO6R+ol*>Z=TSm#y{$P)MQw?M!AmzMSqh5r)W z6efmxE`B|8Z-Uj`;CZUI1TW4?%(isrd$2uIt841vjlX`>cAdJl>)@|f&qaJ&yx&HJ zG3Y&A@6YX;BB+({V`ZcN@(hDr9zXL^zpBWay`A$TVsX~oxXFBe_G!7=F-LFA_+eU{ zoRt`yTvT}eQpmL2Dc5gI{rdaFHv`S*ay@2NZVO63?<y@?8*RPKSu51<dM5ifzngFM z&rUACTso`n;DIT3<ILmc&-1yS-=ukrQ%>%jNuwr@={*zMc`HALEIWNs<Zpy_Yo_I4 z8(!{u=9vyPQ5zz1xc#opE3tj&y}xVv3hv(mSEi|n8u{Mcu%XVBd9v@_j@3z#mX2#K zUt{*2xc2k>ERDd|uc8}U1f4yv?)oz+B=q%1_NyItR=>9A`l^`{75j&`^z5!bL7|tH z>h14Xo8i(aB-dIc{AZuuzqYQ_*t(U+Zl>6N+Z|xf*%#q&vvOJCwyIN`zp7iT^Zzqf zS9`^da%Gjrth+2+emQp>bXEWP!d74JqWZnpo8=BKXAV9hKe6&;(a%VWmkTcLJ^%UM zw>g&%8>`*#SUbI?T%|@}?~R=e$5q((b?CEhPZ63o#q-~!4ArN)ni)^q>!z6Gdv1BV zvqtsevT5@sY1*oG?ECpg<&j<C<wRA{Qj@cZPVOe1-G9IAwmPF=VEuiM-&>J>ubfbq zvyE%I4^7vbv6MUQWmDv?glSObPoY?Y+4Gf~{+~CQ?z3XTf=@vkcYpPm+wm>tg6rm> zGtB~@AD(%(VCJ3hZS3i8-_JbJ3;tv7I>%T$xH9h29`n{1<H@@#neLx`p&4Ut9Y5uD z+u9FDt@DKb>K(|PeCzpVi(H`vdqk%D@+BNPHv4+&<QESuA4jq**MGE0GetALsCwfB zCfysRx@$@|DeeimJ8ji%?vT4?M?Y!mI(=C!vXRO2ykhF*U2zQy&c6CqnUX7IqVIa= z+2OEBM|@vDv24{-`{x<mb|iPkbM?L7Z_cc%ominRJz>k7*-OQv{0t2(C;sf574P$F zhRcH`ESnZBzuWTe@^fz?R_2RucbAtnMd|%G`eSQ)^j;<tVY4aTx``WKzI44JTW`oB zd^9mKMR?H%OHOtRtF(gSC!cl5i!YVB+4b>aq5M>@729@RDcoPFqI!GAyag_2_1oqt zozU%`qw;Is<QXRN!EToh>+C*0Q()OUt>wo!TJ8#QeYvh%wMdjpyzy1UZQ*%)#7tBg zKIMHk+#5Wjd!DI4Td(#u8J^3#rFj<|+H$<kcYpS>`MsLodTSn=ubq5<!W4t%%UoP< z+s|H2_!W1(#&?x(_E}Sh>!QyTye~Mf5woAS!MJ3W*~7^-Jd$lT^A{`j6))MEd2>f| z`Vs!SZLZR_H{Snaw~IgFX<qy^T8%fm{@IQzSC}7~8fn%^RExhkw3TCiS6cY0t5fc# zY<is{Id}4ZJEmqY!@?wi4x2q4&ZW;hA6<_QTe5#zeZ=4QCMs7WN*t0@^^+_%t=`G@ z*`Zm`_vpEM;x;LQ$$_<JO=mQ)Dc|nuWpfSq=*_a=ixl^6iGxC~weAT_kDt7#u(tNu z=8VPVj4k0DYd(rHWw#%TnlpRt-<<_dy(d2{o~vMV`eF6N0M`DMy!m<@$7)T#E^(Y* zyC`_wXLZKN5D8v4g=Y=BgePgl3Y;y7$>GsGzkctz?FT=qoO<A7=3q2M*!FYrp){wH zQcj+M!kg!<`nzY%Y7zfGH91;$)ouUos=JozYtGjx+IxR-x8(ek^~t67g5kcA(^t7h z<uF^x+NGQFX#{3mYxOv*pT_&CKwaNnhh5u$!Nb$>B_{7!*PAao_;Z?+`NuP>b>6wE zr1(8_zA`;(-~XB2KJT@bRK;8Ms+HanIG?&xSn}X`&p_rGS43u6JwDFL;bk_#+hfy( zFH2Oi>PnBO2*!x1dh*zRPOQ%<DZleC<3Y;&6N{^-tY({jt$uR<UfWM^7R~f=FzK7S z!tqIs%i8D5gnuR|H*j6;WI4!ib=INeQw)n-C)W8bIHh<%e$j_J%h}R)<O#2|Q2eAJ zuKvb0FyOG3_)_*`XG4vTmr6gHnzy<={v(&9m4x#r)3#>YM)68X*|0Wo>&FU?e7An< zh+mmM+h^A7`B!ggeoQ&|XnL{H=frOz7sJwHf5(NsUaz;`=I6#1o{Nvpt3J6I@#SF4 zmDfuAYFDgkHfd~mlc(M?J2B)7Q`6Z^30kVc_P2gaxjym5!sH9@%TN1H^v~VA?dSdJ z&z5gj5t_fOU-w_i-@CVNS#s=u{Q2$Lxo_{j@A2<;IKZ*uWb?cI7k}QrX~<Twt*rL< z)qB_e^|MD;vu|Dd^wG~WySvfnrFKc*-WtAjt?$2$mBuc*&sXF(vxQ6dc}M<dude=4 z{`=~`Y5&CScSryJeLwg8-dpvh1snG6=iQU=`$2;Ewg1<YuK#~<k%@6?Y~H2c`d^ay zKNRIwrvB;r@$%QF+36?q|J{gRxH>TBx<G$iKlADQxHTU>E8e)UO#lAM(?LH~Io|LI zPN_M+-z8LSk5mMc>1*Mv3p0*sc^g?y+O}bn()(@f!Ux|qe7dsvy;jbHE7$j}pHbJY z$MvE2y*A&Mz56!qZNC5eTJzQC?Cd|Hcf?#PjGlk*YU=K@pUuTzPHT{_m}a?xS;~R& z<*vmEwW+B~FPqoizaY+&9enA6V{ue{b^)u+s{N1o*b*cc)UK2cI=+5AgXpoVp096Z z#5C=^_u{){(E+Xx=kE2r><HkxP*r=qVuSDDBDoxc;|1v<cLY8pRGCTn)?M9@Rc@-4 zXL)yFH~YbW_zUMxK6U;5<j;>!iz@44m&Rzg1U~ud`})bNJ%wdVXIbXX`ncL!iQx|W z>CYdklv`$0vxJHmn7m>!FyW0c)suB&om-&A(ca23VXuG?^Q*#FcdxGg?r30h=guDH zqaQEI<Z~RI+;d7$v2HW_tEKy;W=`9%{K8Wat0T8^rFFM$`_Ochd%ftJqTV?X7a4?& ze6G4&NnCi9CFzHmyG+UNXP>?-DqOQHO_xRS(bmKBOx$Dp--YsDm;K5o&_35&>V4F9 z<p|T&cUU4tvO4A~3;f$DrS)M+k+I<Qqp#M+_SY<X%@uWZ;;O`>w*%L=ThD2VcF6s> zcF}=#ta-a1+lS;V&#qmypYhPPCBLWFuXWzN;(hovH^=<P?0>g;%eA%|3pYhf_Sd!$ z&D~fgIVmMHFv@rpdrHCe8?#of`Fs9<PT0NK(tFqT%G>`r{_B5}B<Jc^A1~gJT)S|W z;flMJ?=m88M%C}H-LX-Y^GNW~pvP-(1YOz@r<$a6aZVz4M(3(!Cf?qD##MC(_B?89 znaZ|WxZESPMtSYIezAL+3euO>mOTucuzp(B!%P37Z`H?d{JVYg_V0(UoxAk!_p!J3 zEB{YP{4KiSf5zFxf6F&)-@1GMR_53B@^w0I_vg3$fB#PP=l^q){_D5=|G(hlfBEvb z+_!J8Z7bjYy^ODHde8&ur~flfOxyb}{_T7JNB`MxN3Y+u?OXi8U-xg{zWeXojrdRh zm;T%T<iGdd`k#>&|Mf4k&4~MNf8&1T)+_&~|EWLuU;Nbn`a5<NTet6h^56U4{+qma zHr=ro{_+3dx7BNH7yf_$wvn;n-~7Mfr~m$Mt;zVk_wKXmN4Il#KF_o2lMcABVZRbH zgMk@;Wb2Jh=FF4LHtTK;yuW#E-SqoW=Q0%J=N~8+WHFGtv{(L*%w)|~S^nFzOm_IM z)_%-+ELQNg{vuwV`&Nf9Tw7Im(>!;1YUQ?@+y8IaGj(cq1Gid{fyt{x>l(XWmfdRm zRaS-ndiG#jwiJK+G3T@Vd*r6AT2uS~^|9~Gz3+ElzrWx1&%ZYxeuusNeec$<--mne z@*k_0$o?O*x{G&{nXE(~=VWd95T64_FMN8D$IJT7D*tn53TNBdZ|$|kcgiwehuPH{ z{8oOOe*JC0C1YQ9`)P9n;)3(|H%|LlS8}uChUc@|FVWZEdY8;JQK<aNou`q^$8+zS zlW~mT)LXW~<-d=Yo>70~>m1G#b#1E0j1Y4pxl@<5@&h*I?pyReqGh`Jt^RE*i{9R< z+Q04ov*6>VH3yCN7w7Yyd9m8SgyrNr@!M5CeHp*5Rq(hA?ci+QQU2F~InMv>Qg!F^ zbsK(Pn|n3)^n?B@)16=Zy7+a=Ealy2drx2eEqCw4>xLB0m@QG9w>gzmi{jkds~<1# zG2t|rCwAfbgMJ3txqVl}m>qUsi>dJKuDP_?*8YK=aXar^AFZTsRb}_Zx-B<Pd0kqt zD(L>|g9i-M^rxvTQ)8HM-87zwAxAi@c)RUFMX#N+LRO^nz4>Rce#)XYpH1hV@j8TB z{Hp6Y+?A7%WWH3Ogy~r3%o%)wSI;uvm$sa7fAPVl7$v56dtcu7Kcb$N>%*O4qh6p| zcp*maNezqS_a3L#a26f*dZrE6ZyZjE2wvFDtFT8?Ieph=j^p{<g~_Fhb9QTJFBkpB zarO50#}fHXt+zOs&hL|Don~)aKWj^#y0M(>B+bgMl??VhyiX!4j<J|c7h%8Nao1*! z`sx@i&dDpL>QzZi@$7VoUl<b^(tUmL#YI0jMAar9SyklYyDF-C%3iBXnZpHPjxJ@P z1<I;bk7j<8SkjqqVBB?UWumRtw|A>5YcK7qDDT@UZ)?5bmP7wb-wW9>+<LBhc>)hV zWqsF7HQU~Q>}BQ+c9B!>n`fQOw>q?A*})VQ$r*kzs=Vf17Z-2u)o$5doL}|l$@F7W zYko8|HhlW|`dQ`USK&1^+1AU<!<HTv4~VNTziadV>(`e@vui|eocpou{k^vQb^iYf zb?+xUn^U1Yf0g>C)(zioo-F+Q%x9WRL~OMQ$LY_}k=^&(O8xcE)lV}0y{=gN+F|oe zV*5B>&zW<7&com>?|*o{ezNN3g350v7fkYB|8ru?p31W?xDExHpTD}G@sP{TZtg7Z z$fX%Cc}{qUd}VjwU!~LUx98EpmF15zZ{&Se|M=qCzF`0RbK*>1B(8ry>(R}RN6)^# zEL?M=v@t*W(aV#8pL^PGZnaWa!&-8@H(QU}MzN;ou1&E2#c5NL?W{9n&ClsoUOAM& zd;jF|KToa;tJ&<~(Nd|cJed)AXnK&6+biB#QNcc0iyim-e0<IO_f==S{pI!jNk;$t zE`Qiv;l3n+%PFDYsZgdswIOSKrFZtDIGr}P?t7gx-W=2a^4jr_lF1AvPTp1Nr>g!h ziLdX_TzW6x_5J!xp6y9I>gFy>lt1>}+9R5~Pwhk=Ys&ijm)2K%s`)5A5<gg}{h-G8 z@$RWQ57d8^s(Va)Aj4tN&oQm9;c0r)=f@64l4*vI#2v2*PM904-Iwune#j^O$VqNj z1eL9n=9IFWtE+RjwdpDs|8h=r|BR)aD?lcHeBE*E`bX7=Mkl-CuQ-Q)De#-}-eb}7 z$`}6>Bbkg@K6Y1acX@w?RYllh;l-$=E%_@_{HN4>Hvjci|6}*Fh3d~9@;crX4%n~w z>ka3xKb<WP<_a|03(hHLIu|@^@xB?0=V#W)KmAeB$Q4ny?4MoNKfe{C-djEy|NW&= z_t$0dUg5=mJJX)}ojDaP^>(ks+vr#C<Gy^K_G`EJ-@U3l_qciXExq^N^?g34{&yz* z{FUw17o8`koe?v3+xTVmHjSH0F5XJo;(MrD_roQXh#W@m$q5@-b$nkPoMwBWYWvZu z|DCVyo~$|(eDudZxA*^4@BQt4@icyt5~sI3>$JLMKYwdHd!H_K*xj&g{>uIRi}q_T zO7Rc)bpFaS_nT_H?-$SUmHO>&_-%e?l^xfspEKRQ1opg0j|!DP9<*g+fbjkdo?64U z;8*MQe_5w~RBu&18yJ7)qGs=U{bS{)ltQ@tU+vYevS0j>_sEZP89dA<O*w>_8#|2` zZEjq!*?3ykqO<ckHd!;?lssr8uwjm189USN^dqKhP1!LQGi(iS88=laEU;U?(K_kP z^DE8D*R2Ell~+8Uv!IOS%5xXnK2=uR)0H3leiggaKW}k#PxvsWs@&zhuT-<{v4X;u z{df9)xNd&gb#u>xk2{lU#E<yK9`x1cXkK^Vf$COEk=(dTKiZONriT=1c<ozQZu_&( zz+Pm=ew8!)tk3@YZT`7?##!xGcZK)HU+l0kT%@h_vUka?LtNcITqVA+vPECntzVUY z@kXuTH?iJp;)`<w`S-n8=(_n)cVy<pj9SB6Vi#xXKQ+-#32I#w`SIwQEfG_N9$PQ} zCv)*WXQF4C_tp%TeKLY;edE`h6`T4c)pL<te873ruW}vt)@S}@4H8uIVPO)!-qPui z@MzXo$EE)^ebTNIjAak<i{CIwW2$=C+#~u`;wQ>k(iI-;QLABNnt$Eon?ujvSq2gu zJaLyZm<?}9H&v-D*tc+!a^R=7D9O&SypGNNEb0GSk9|-$_JRB0PlX46S|8L16zo&> zvElNO5j<zbl%D@0-2YFN`&T*Fz4ZcdcAR_uc-i*2^6w8ixl!Y%|Eq`m7Z2NK=KYsw zUA6Q}&*r(aOj=JC3rlT0#a|%tOEJ0c_99(Z-`APhnc|WUbk}xvX^9HozjQOe?@7_) zX{nM4KPPNg-*>%fX5GJs&z9LsE&9CPZFXG3x@$4-^Mp_Rn*Hfy+n&?O&2#Of`Kzm? zna^|_&F$-5*dDFinESK-=G_IiQx<bo9+}y;{<4hisi}%<8#;D33obczq2TF0->&dl zp<DB$xb{pj=X2IdG5j7}bgO^s=|{!2&AT4wpDWC)6+2WY*VEmi-Bl{PN~S~o+yUub zX%^x?YlI8W%+`{7b^Jlv?>~=HZ*N?9T>FC6mLCjTa^}BS{Ic|Rg7N)lW#^6_nRKFj z)$t268fWFR$_7>mpYS*y$Tqd}^ogJj?IV+lyt|!QE>E9&Yv%R*)u+mfU%%zGU7cRf zRsY-h^6$OtE5Gi|^Z(6SdfVC9VW&}McCv}j!~GiGe7)=LaxP+x^mrzEe7^kJjq}5P z-*^?Rxiz@UT=Rue;HLLwXEc_7(mivJKPFesqBz?5*n4I36L-zF%C6>JA$7xV;a|?b zf3{k*OuQ_#dHd%p4?A|+Ivy^||I_{U_V%*-e8*CA9u?0P@2|9;8Cd2tJ6_oA_wqYU zj~+|;+&;*?aZ6m^q34Talp>E6yKp_~R&rFFY<?%mZMNY~)-vI_f&1@^u^)O_sN1^j zua~0SJ^MFN^KaFj-pT#0xJjYrH^27tQuF7syB>Uv4W6aIqI|1S^oh9F(Y=crQ|`1T zKVB=-{%Mu(+MS*y3{!6W)X3(l@m*#7<xS(u-rFT^2Teq)*QMVq_nU1w+ig$&kE7?W z?Z^nYWO-punXJ^wi<xHge=K2t`%WiIF_-<-qgNe&%f7hoDmbyP#r_g&g`b<;Khbjw zwb!-OI~T7LeE01f^PX*)F*!V&4|#7kR*YG9IQ3E1Wu?bO8zy?L5}T^I<mgc^qwUvb zpIfw-X{}Gt*Fz7*noajQ2|Zc)N>t!rlYv@x_RA|DpZdLaO4B%<cQUH){yia`u!q@^ zxq;2TL5^&tDH?0T!{iUIKm2ItX*036XM|^GIIS#~+o#CnIc2BN`Xm=y$vNsQj2~yR zC@^n`QC498_hrVODcNyfRb@iEg^EwJhi$xj;7Q9wj&=zik$oTEmwuit!xVXTlKy+= z7}4`uYb)p5W&G=F(VG3vOJhl2S*-Q+Xw^UYo{K}{vgKMm<L1Y)a9mjGxce;cZSG`k z<L(uw(~FbJ7S8v4f16KkNr$FjrElc?HRm#zy1&iXbbDg=>q}{R8(Fv#&u*@%nJD~t z)l{#F%|eYYq<YKG79O0$eEsB>H<RRoQkXgQtS+v%s$G%&Y|-%(dryS%%4g23z4`ge zY5U&w9(F>Bysk43eR-2`l4GBZ+lSK4426*a@4TM5t}d&~d7iv)^_OI6XVc<SC$<>* z<nk!(E>wD9uyxDRlH${9KQH%u{ISzVtEXFkzO(29r=5Ee1iM3$ENxSDj8{9Zc^$LI z_{W}<kV_7;Vovzg%{X?nhu!1G1&%)RN0rxXPg(dp^y<rft@3>3io<<RbF`R(Cth3B zeIUK``TngRL#{qK*YLGrx#Q{U>OZ^#b04s!*{g(#^3-IkNEKIX2@;B*R}z-|Wx8wD z$u-lJzwPkfDQSLiVnEGl#>H_H<V_bGxUqdQ-}@<VbzKkcNc=WWX5~Y<Bkhr9Tk5tQ zo5|2pU3^E>Yi5KN%O@8F<K2_fZf;|2b8c3;bJ+cv`rnHOjOM<0zfQLH5&PY;>s1r_ zr%bNQ_{@2fa}DP{-9R<InCpc%dR4DoxYjJyIe*jo>5ZkK>Mo~w1zr{hUXk8)q)JMD z_l|E?M`!+f_x7Y{>jc{-na!6TDN4(%%1m0b?AC*CyDl?6NNU~kPg-V9#;F%a9t+ns z+=%GywNOsdc4;^37SvOneC)Pl+`<g=<6->~0bUBee(fjk7425yNef7@o^{~;$G_fE zff`@bJ(}-5;ZfjwU9xtwgm;qa#MzQl4|p6t)Y;w9z5032IsT125A!xDFiyJ@{>R#@ zX^*G#hi6T?IeRpwWSWXdPZG>_74P4s?e;76m6g@rW7Q(-X78V~W&P~ybK<YOm~6xM zhP~Trs^j+cp`0@=D%2F$UbV=dYqrk6@37fA+shwM)?J#lV+Y$d$J-qh+aG4d1P8A2 zxF~q9*!Eh+rMBxf`Ez4BTeJgIQq``WeA#)TZ_$d$S991unq1(RY}E8!#pAg6me(Bh zDO2=VRS(Pm{5_|B{^>WWT(4T~KYh2KHD|_?zlZB4+;m*uuV+#C<k~)0PBn&{Ir;A& z1^-f-XBsWD$2UI3?Zi(*|J%_It`}{aWnbv{M|-=Er90>UQ|i~<|2+BS@l3hnoB!c& z{?U6jcGbJ;{Fbyoxc^b7!;#dEPVX$Ke;hM6pDvXvf17u1il=}1&db+ww)W5Rc(`8k z+0K{pHv?X7^;y#tE^@xtzczGnX>ny`RZ&?{-Q8yo-Y>f^#oJ!Xtz5bO?v$b^_QaDL z<Xav+`m?LDZm~1dwS8}UOfp;q+dTI0E_8~lyjrt%>w&m6w>PjxwnR<Hul3Yf`|ak* z(#JavI)2Lc{qNHvv0CrR?{Cs!T(ef4kX|XDV7z}$%+^`r&lgRNx2TUbRl2uL|6YOc zqra~HQ!VT(r)!kv*{X5J#m)V5Y0nPNZIv%0`L|hnW&Yk&SSl-Kyw_o$^MQ{`8>He} zr{={m-`vl7#q7MRZ{nNs*$)q_^SjsZt)y<r*#lFrGTU<T@R_o%5;)sfwchvf(Tl!4 zDSfUJc9>0EB;dcK;%)YklCqmNy%#PebeLDQEOB9FQN6f(!#Dlj)oIKb(rQ0-=BVy* zI?kCek6p@4f1Sbkt%Xv$)ejTTt-jeWnkUD6<gBuWZaDAycYQani}CusJh_{L@8Xxs zh8?UdzdlUe$Fk1hk?i*SF@?AI^ceY%#D4EpH?Am%jJp#fJ69tk`rV1w5mIx))$8|X z#<?o|sAZWok&RJQK;gn}fwu1JYq_U5Cw}dYzVBMO<ke}VD-AWTvu6rkT<}U#g!ych zM<{>Xc84AEf@{t548N^fTr_9>{Wuxng!Gc`weo4P^ACv3d+gF2cW||I|CUXE(kdRW zKeMT_w(E!LGPRXc&aCa0`?PjK*n0oId-H@n6HbSmd3EQpYG`eaY5ZOV-+U>SiIWw0 z<vjxCXeHaa@$o*8>R+Zm=e&ad18a#FjPbvEMGpmY{HrTIbn-{YS_fyl%nK7Yv!z`Q z{L~ur?8BC<ZTj`SA5U!galyfRism<#;)iKp6uU~k9((QPy=?Vl{*?vEo1AXQOq6<F zvhvPPCf>l8JbT*t?n`bsU)Qn4Gr*{2)88dOPBcbLU3gjZ&B25vj=n4QWbIj~`LZfa zKi`d^Frw-G9CKNQOYgpa3^HHceanx9f6I!Zy%H<sVsi7<zGy7_@$yDWn0C3<eZwlg zzy-e@RW6xrG8JCC{=N3f!#!N@E<UMj%Y5K^_pprZyuJv-c|SI0r%X|rD%zXU`SW?u znNOUePghp^7u777VbgW0UpBeKdeiS%vy)eod4kgPlk#MYt3^L|uUP!^Q+K7)q33f8 zuFho$Drd5}%XFZm+p)=A?cU|Dl{bGo8BDKCUBnXnuQH}YX5yXv6ZbezaLk+k>&CiA zg5Qf>4s5<1wO8$W$r^^=8;iR-8tT{f>{FcB@$332P5IAHR{WVzFLLX)U-!-Mo+Sa? zteg4O#1u}=i{QEzxjVx1fWz%#`M-0NvW_dIU%DdZ<|nx|d19d3{kYjx7hS`GUvbTO z_GkB-QuEBt+SKmlJezuR)X(ltowX|ZXwaf9XJ2Ooh3ZVs+9k~D7%vt1F<Jhu;62eZ zCk-~|-A`kG<RjS_+_U$yg_>)&e;RjcvC`*<e7keR7pYd79NLnedP(!pTm?S|mr&Oo zM}yDkuHTikGhD2F70;)`_m|zy@wct1d?h-gEBtlv^Lr)l9-Uq$^JJCqLjL6TJ=6BA zx#2K>`_xa*{8mopoX~Mttf_5J)5ljD72H>!UDluc*PUNS^GZmM)2GQjnwJgj3;KDN ze#p7y^Yg%Jy*sDEJUdQ3o>O1tG~;Z=iqO9Al`H1I)b7cC`5|w)C}(-O%f^>xk6e~s zF*z{#+Sky@v9l5$vd`0vo#ozpEwH)#qSdndhPz*>tbG0L=h>AOUPcO2J?3d$&6Dwz zU;cR8S-%&zk3=0;&zCY^{^@{c=C!rU60GMps-N~hxI)D2$&uw}KDNuOx|pW5x8d~` z_a{3qyf8D$zj!u(`Ptp;guUGtKPx&mZ=>ma7Mn&P&zjC%{<h1!{p9DFOs;%wQF~Ct ze`1>1Cq-?|NN;yP|4HXOn)%$nC9b<&HSN2-?)&<vd;hoZ`L9{`UwA`ELS~$1xr6Vn z|M~wF3jg1~ckbM$f6HBKj@<S7|H&|Ys(zW0(h5ewE4v!C_2a#cEsf{VU7q@I;|p~k zZPA=1-?m>ny0bzcSU#W0%IWxnR|?#`N=A1WdETux;JDWiH+wDj<M!sYxy{=*EoAtU z{JSkVGIn+LoxYXT&A<6g{VV_W?_pZewES8)@Aq%<Ok$J%*k+t$`<c7w7VrC24_|Ca zT66HhU%!a`X}|Rj2Svtr?)~QOEK$oOA8KV>zgI2MQ6o+!J@(Z9rGMf<g#U^E{x6On zPr36mw1M+eefjgNaX$a{H~rUr`d`WJ(*MW&iL2HsPl%p#p;+m;eO;HHN0$GTWh!!0 zPQ~ta535M{VA}t^V$r(`uM#3eXFLu(FL19<cxNWZUk&y72UdJlFW1$VTVycHE>6(+ z*y`j5hObzbJx=nFntJNx7nb}k?OThtHZJAee7iOAck$P1yQ2;Zjk}sn<la7zGw9mI z-*<b_ugbYQ4t}YfabXwt=I4EL^89Y+$GpGxu1q(*==Ph%%2Rozmd!nDv*P?2yR7iA z@}kovwftMGCxjNwTB<NV>_Ju7&bOxwvP+l~e@wnC>Hm(Q<MF|F8Q#uvlCoLb8&)Zv z;aaogPb7n>$g`av8K!vNp5waf?S;APF6{fAaCj5%3<d{7SEpz3FSa=yaNsf!dGh*f zwCAHcZ>~wa;_X_z;BnutSgE|@vOI1Q2~rwC*ZUrSTX|Q8K}uP}-|+N}<it%Pfwmi_ zDSs`t$})Un@Q`nLil}_f`6B`OTe2=3TcF@{$5-gB&%5Gj^A0FDD)pURZMpLJ?8N(~ z+-nXBP7SU(EPqkVC;!U%%->xHH4aT%u|VZUv`qY~riiS3@89{E|EFgB|GQ)F{{6eR z{Gax1{$5Li_QR9z?4SH*|K7iEnYaAs+qV7Nw(r}&U--X!^OpZ&pHCM4EV8RKop&%c zG|?vXp5fY0YmbIbtc-tZ^1a2_@{7g^zC~X48eA`SK6Pn4kXx+a<LdTOHtX)I>8jzW zUd}vcN|PV2PvS^AyuH1#SyU@l`1i%v$Lb|-FFbwSII-*THjn(by+NyAbQqt0u-RWG zJg;-{;^`s3wtn^4)59^*@YS*EeT^b>@BKMjcIb^{;meh}?=;uCGEM8Ln(KbzsNIX? zhh49a?Z28X&)V#4t0^4N?#I(9{Nbu!-R*aeez@E@Q(YIadAEsE;d!lDqAU-7ujLnd z$WVFY;Jkkm&$@nKIP3aMuc=ey1BdQO$@#V0PWFTb&+FHa-?&I2h2w~!{GoG)Em{S{ zTxQq2cRA&5uJTVv&PlNHT&lQ{rDbr)dTs}oZh57%uFJIS0&ll>u3J7^-jlJYL0Hqu zWn~$Ir&Q40h4P12SWmf8(tg9}<KkI4ZDB?t3vFb0)j!qBg}KD1E^^`3@8WH;Y~ym= zZ93(z-*%;Qr3YWE+a<wVw_Ysnpuv=?q+N{<y0$Fv^|I}n)5I(AOZCo|<XT%BaTTF5 zy>N~FCu0^o+PZkU-Zq<+FCK-ZUwfot@abBb%(<c$6F!=~-IbESs`;tWMltj#qpQu$ zyIB=UeA8E~y#M;s4UbzJMctpCFj-mEk(1-1uxFl9$f~5?j`9z)e?7c+ZNJ0rm##Pd z@2>XzU7w!$U;oIz|Bl=L!)ABBgJ*Z*8uBmyTOV0oF1_t?vAK85|MlO#8$aG(aCY<G z|Iowz|K6>Q`2XAccm2!%v7i34{;Hq(U;poZ?|=S({(pKt-|U0J0`;%|-zh#l`s4pW zxsL9o|H~QWB~NZp>`SvYDa*3fem>>aktZ7#-4mF&W{Vs185>KJzWDfq*^i54?(FU> z%(`Foq2lRU>kVdYPv%eEo^EevcMbJCzs3VL!aWZH*>#LgPp{^`aQqq9yH}4n*QPHM zZ)p6%XQ(fi7a`GCoU!KB`&Gxj_I~8M6=(V{+u?k+N%a4<-+x>eEtEgJF!09dRPg-) zlcrw~TdBT*HRH}Ise0qNf(l1(FdEH|ki4k6AvI`w$>|+?Vv>TdUYFiwx6>;7qT&H} z@#n{VeI{i~R!BYYeZ3?rW^PPetjzs@cQI4FWX%nA-+$$`^UN*Soz`MkBDhglzxnqE zCgs&__5E>yHogsucj)Fn_<YiB-Q}lYCpH@%$~<&HXuGvix6Ql52d!eIjal<wK2frn zu)2Fe!JhK&w-xtqwAI;^mz3xK>4@wQky1UsV<yY`*QyNfb{yWAe*Z4}oUELHh^mId zS89SXa$zigkKgiMt+}}3osIDMrY9@P8kfr)fZPZ$o%4ZP--)d}E^oNDXf0$eal9E( zEYt4hnsYjRf<f`k;@_c%zv%p2?BDG4p4E2g=^zcU<E3Gb_NlB=Xf9r0%eJ7c(1YcA z!4uxt1s4j;4((m^Bf~X&wTa996*perY5CnD?fz!1;{woK04HarB+ZeX(!F)r9P5bW z1girj6F3C;z&8Pefo=l0z!c*0clH%`sb_MXGaa%;r4<%uetrK|QU20h<~97f>ziXk zz!w4J#X89Q2kbc**r3Ta<vzn@E*rmXJihm%_!L$qAHL#Vb@9PDwVCmEFRlt~-1cGi z_Fe0OdtVB?lY8@y<Mub6x%-lMBj+cW%-||)e=K!lpFelci|OLBzRz8Ro(W5bYlbWP z9d!0$a@}vU_w7ZW+9P`G6}+1`_I!HWl4L#iUq=A@nT9*9wbc#nixq8u<mp$qY!ZFg zEzuU$JFi$YyN^3eHU8Dja^;D~?;Kuiwz<8m@VCCg#wQni($Ac?XyIdA`uAL8E9bL{ zxTHCW4;;_FigBAW!$Ib*j((J>MDLXx)2@byXv30{BZ-S<ENeR5ezA~U<k`i}-GWD! z6viItuxL7R{M(H73m^5X(#oZ(?(MvHoaJ&=OS_5Eqxl{;9}2N_>bA{{Xz0l@{KFWr zxJ~o1G;95(ADN;{nT4v3i!8}f`!VgwxduI+zR7Q98fH&?EqOCuV8I$yAFmh5zM%;T zpws`~1mD@%vEa?A9Vgj#u6XOeVa4xvkE_hKz4#Dp_5QZQk)NvzyAJKUT&TK1ID2BD zDtnt<NzZn*YZsn2hjnVrJf1Y&<n9hO`S)+n)pA`vB+TLXjPdvZW|a<=f~yQ%N3BeC zW(Z!NyuTp4<)mx;*^O?Y7Mf>gan9Xc8`Tpq*MFJs!kJ5IIzL~JYq1UOwWwk(E8N;) zxje5W<V(OrpAVe7-ZYoJV$3($)A%&<uVL(NmyW%xtDLJ2*Y=cpnryjz$=F(jWwqw6 zCZ{?kk0bM*e%rK?&0l(=RiM_<BiCmo$!Zp8v~;uTmvXbpn@P>|j#7?Yc=Bj;iRAPU z=~Jn^>sIO7+2l?O`u@AH@JWAO<8sbrYF|wkg-HoEYEP3X_4uT@u<hu|Baa#W%B)<W zU8NDr!4u=YT})v&yT+_Fe?%|0z1R{a_c&{f@3r<R5sjxrf*$Qu@L6RMy*+LIi;ou% z|LPO7=&d+-b*h<VSck`v<Ol9ayX6DaPYQ44oVV&b=l@m%sf=lf$`v=bwyf$*Tk2F~ zvVFc<lf!q3NDU$DCDI*}e9SanM(z%_T5V@}Rm4nep<Hg5!1{#b5;wa{+nNd5ABz{R z+po+wM`Y(U_0A<4d@8YzPsTg%HZF3vGvMCfXs@LG&1tRCx?NHGYM*~-{K0ot)7L@E zRrzv^?eP!7&d*u5UOlO!oc3O0%ZaIR5usNE`~Fl5Fdy5&u8^<G?flwW%u`OH=U#l# z#@`ap-?G%QEPj0G&xT!1ZEf4mT$X(7clHP8)ex5F9t*v*R_)mDeX1pbd8J$CsZH0G zcCtn_E>yha5XP3Q^mfJ<m4JPW+zTxE*D@GLsAngf{rhfl@2(k-t)yKX?Go7P^BShT zNPIKvdEePOgL^M3#g1)lT=eHbSpY+7mhmC^1_qC8sjNe@<Q`dh7CcyD@o4f|hS!h2 z+{pUjlENEOSoX{7;-$BrOpJX_@)^Ym2`pJ*c;xXV^|J8UH@t;gkA~Z<7VYa?viLaj zNgj@bco$s>=VOg#uM_MX7k_`&>>5=h<M3(ojv4*#ht9nEzWPyo->xT|p*5ZoYEHY= zzKP2lF6ww5=9I|SUR$ESgHM3>EZe6r#;oP}w+!@S%u+8j<YxKIXFd8{mRs1<=e*jw z3!fXby}Yk%db}w%-9fbeuEFnh$()`1Ilsd0>{Tm~x!oP!!5^|rUeNLIh6v9-Chc8S zPcA=-oOZn@jsK-u;^AKhJPXgR@Z@=8&31B+@kdj`#D^DFwlrBJo~~H;K3^b-mrF=$ z;l7jm8<Tt%=iB{KwssKtvesHGtt5+yUu~uE(H-S-%+G>#GZpp~>{Pk^x@EHEw8K+B zn=71^|GXw+M_^aq>M56gDugXE`E$rr$7R<QtH@m^XMcONCGA(x!K2R0R0LN?HiTXL z_kP*tMSEuzroNOrDb;9Va9r_uZ?XG>%iFH}4f>hVH_a!w^Obpt6_c9JmkufUKc&J_ zo>yuQt@2@8zP3$GTT#z*74zw&td~1ytUOuO_he;zWR=^|nDm~WhDq-WY&h(0H#?}A zEnu3tDlbW8O`Vm6eV@SOC$V=9{XX9zCD{HnthrUTZJ}m!nZd8h8#7-hb~aU}TYI#> zk^K;Sz-ii=X+qo1rn8qx2HuFXbCKm$I)6x5dG)2bi!rt-dl{D$sw`nx!obP7PAh3r zYgvHk>eXF2d$SkHMfnEq%gAJT_(|M?WApap52>APE7HycIc#%1P!@YGbE}Pv-J<!H z40o?jv^uneYjXdScUDI6uJMO1xC=$u?%$CoH+PLxMWoT$>2={9vP%*p;@?W0_KMut zIdeg!UuMuQIUnZD$4+h+5ZXS~iucosi(4{<&&;%t<e$(MrfbBnd3Nb}pI0^lADyCW zPk*^+<9C}^IMi8>iA!y6hsFUj)iV$0v`F|Y4YC(s_Ww$2XiLWBA3j$EyA0QN=`VU! zAfCl=vMy%*EL-ViSC*QtU%laJ(1shQBPK4%uzj#pRr%A|n{nmL?Dk>BC$FbBWVHlt zTo%5#<YwQFgX+~*CRU27-LYDyBzeu^Uu<#c)swZ^IIVMWpK^7ym(HxadUf9~<XzRY zUTSKo(s)owd(ElMPY$;%?Vb82rKI~IBkSFZ4zoA~yC(DWy{)nQ8@Xqinv>Oj2H%z4 zp{bgmU*2D=W0iJ9^scy%Yi0)Pq@514W7lXLmD!*f+|hgTPJOP&3$3u_<r><`M>l!x znissSWT#~=|Mj;^9m0L}&dXVH9+OmC^3F8Od)h5mfuKES6&*TbpLUonTBC5sS#dJk zOT(*om+PFFv2>dC#NR1fy5^dG3vG$o9&emC$4*YGX>x8Y6N8o6F6R~Oxz0up^`(z* zEkC<*)y_cU*yWzxJc=FGJds=XT`iAKGu+ww%PS$f<+$(0mlt~7r9V8s!@FVAEmzgb z%GaAV_U1h9J5w&w&Z0H<@H5b%|7nFgm-;MyF=MM<;qL9Cv$mBdY`%O*s$0}!+O|Ea zI%iWtI6kkjzWn&_y&Y#~Y-}%M(23E?vfEUA_T0-|V(N<~crJN+;gL%xZ(-QyN4J}w zG5p=-#q5&5#zMjA4@<;RsfUM(0#8f~nS9Ux;j#(W9}46)Iz2udv&hR?g^_DQ_d-V& zS+%kcz0;Cj3Ari1b5Z#w|K!!w&$>&ZyEMFyzknR~FO_WIe!hbJm)(Q>HDa@+4!xZr zEBR!mqp;P<X&q80BzX63xms|DRsYjr#gGD?7b&NTLSJmXAS<spsr1X{CXQ&N^Zq}c zthm0XuDY-|cTaXqtm(P+v(<I?2*q&!-&v7ta<1OAE^nTEb5usL%ZcTRvhh<S7W&q# zU!BX`qCM>!qt8kAkGpJ~R3&%BZOdR-a{2F(&>3rsd*t_I&HL|ieO*}Z=E<uUZ)Yfd zT>5!S<zMZIk7hsn`qQ)f@HDB7+di;ecy{q@=3}n>b$j<@%-yi<;O_smcV-GN54>r# ze_QrObA`EY5{}uHzqpy9Cg@b<ur^}K3(F}Yx9S+GPuI$qxVt#V+__=rsd4}9jZ?LU z4tX94zp$=ZE@5Ix){@Jg_)RPHmorFPZao`q<-9q~B#>Fq+(^0Rj+)J@$-?pp<$DXe zwEf@du+L~%yK|1r>vj3}A3EN89V)6C+?$iAV$&;pJ-Ag=;|}xd+uN5&2yZBVao+3A ze@_9Xo{~?RyVPp`8gB3Ja4h+Cbos7)VTD7JU6v#!T}n<l&mBE+p<CjGiS}Cz%+yu2 zTJ@>~q6=4i_$bGgH>3O5(iF$|5C8Aqo1VA5Hzo6z`Fy6ebMhu#W$BP@Ssoee7r8E^ zeA(MgZ&tlpd?_(;>IF4UF^5}WzkjTJc82@QWM3Ty#t90YstiF%4^pCprbX=E@%>ou z?uNPpk7qO7zTu#m<{jq9IKxatHseZo_N?uP%J)>7{M7t4e|h4ow_E3SMsv0&zk1AC z@c#F=@cdcJU;pE25v<?nQ1>msE$SfOK?CR248@Vjuhu>5{Lnt*kKAdKiYhj7*Qz}Q z&T|A9_#a8;O)wKZBAvRHe>TtW?)DzJJ12U0)@;a_kd(Y?#jHP~%Zho<$Zd3ZZTn1Q zgX?-BN7bz_{(WND9uR4?@%4uK_k|TYccc0D^>6*<kvu<pPV+gDhCi>ZI`;7f*!8e- z#dTZnJdpLb!^&Ps#(J}*N$u^hD~~c~9IH*LDVEA~o)}}^k|OZV;KM|<uH0=tNf(~V zZEoUyp#Lv?NAXdurmqc)KKh4F_#z$o;OuhC<vp+W`jy=2;L~1od%^?tCvscmJ)2Ix zd}5~VWim<A!Zlr?VEyZzGv+%uHNWJMvM$ellXIN)w$~rk8=W^S-96n5oJ9=pomt~v zIlE^~lY-^hK0hA@{z4{^W!&<7JloEDo;mLE;?}zt$}$U6-dvx(a=m8A@+0p{Z+{X$ zcJ=o4fW8yP`sZr@U;X|4!Q|Kb_q7B#+)_EfDX08-#THJ}nzmWLN}u1<Gs)JAIG|v3 z|5Vmov+d?~5nB&3Et}t8_O{vOa<kE~76Tzu1*aLEGcRx*WYm7}=-a!b>S9jQD8cFV zJqKr<OPhUZO@Yt*t@iKNz3nf`aE-ZX|F!Ug@sed6@&PqAGX%}@!nag=cj{YilPp-< z*56=X8!c_8u#`VfU_tzXhD;9rzK^#rRvu6bce<Yt(-wHcb4#zE>c%!9-;|(4t4>eZ zO&vFKB00EsF!Z{yTThrC;}ADvYe`4Xmw=E0<uBXbR6Jtwo_P0Y)Z6JAClj9JW?Y=a zzv_s`gKvT{<!5wXiN84Bw)JT2yXS&G-du^Z;6Ckm>%;t)2gR?Mefs-<uAbJtaHm79 zH!DhbMDsWAsa(?Mpi<X+MK{oJsp==+B}Yw-Rz0maC~-RW^qUE%53WyG|MlCmu2#i^ zpSm<QExx6C*wt*$T${JmX>%UuEwI>plDoak%XGWv$734Ccg*`HX9n##F<}SC2F_hJ z`{NlKm?v^=IQ(;2>esd~y_@l^xBou1de1B`_i*EUyFXkfU!6Ia6p^}qmQUsS&AUEi zwXQnMTJ-Ox#&0R9;#SXv-|rP=&A9XE;D<K{90Zt^QVuBXS59VqekCDya_iEz3;(_p zzPQCEt*LuR(c0x%V&b-GvrjCW9ilt;e}NpMf8#;R4e6H^_$-drMATo}*<vF2G?95d z<IMC|`T{qPMxL5EU0-r$;>`JTmrktwx_CdshYHSU*_-Q@+t>XxDw@v}{rXJ$g2Ue% z4QD$l{FO@P-Xr@nrt!XtpMcT)J<f%}57;d<v}<0<MyN2vU+|H<#knlLe__wPU2WUW zH1e<Ae&D`fWAt{5vZh}Gtp2Hm+Hpqv<rjzT@%zDC-FemQjr)`zf<{{vuh`yfIC3m6 z;*B)FT5MN_PtdFEDfQM|Oj7^qbc!Zz_*wF>)@<85+gkyaiMjXKFK?>2Qzfb6s{Ce8 z9ZL+uvY&_57M#4#zfnAT`RB`g?%U5<n}2$+VVT^ud5hUQwC+60e^+%?Y}y%5=MAz( z*ER-Pab|7o)e`!((4fc2FX8rkzKpxMHU*wnyN|cFPdm({KR@vg*P2IWa@%a*A78)V z`^AEHm6Epd->d_YcC>!pvOeKM#f|3&B>uB7NHx`(nkc?4`S<Vp{=;|K1-@JV?>?x~ zmYAM!P5i_Pws-%O@4I|RTi$$S8N-_S4_|e(sr4-9cKRG&C|Vy?c`g0LyPa=J{=Lvq z-fb@PLvk*UWT1&j$tw=VLw{s1HJB%GTGiKg-fE4W%$fI{vFE93n}f&=y`9X>_ZO)@ zzH(MBqMcj5!})P{MMgm&)AI<)mY6S$e-eUu)#fbBJG`xJf}^wE|M&}A5`Hpl*E6Wi zI$q{zyTj?-y~sy3IU0&t`cvPOt>L}KdFXhPiG$M38S)Eq4kdrs{<hDaO?&x$N2BQT zWr^AkzUC(VY;anZ>bF6>`R-xPI?1-j7BUr_(f&V*&$}&KexaX5<dAXCf}*Y!TvCVk z6kbSK=d<klKl4U*rVs!B?En4nP5nQ8y*5Es1y4gB{XH#whj$!{ulvod;ieJVvt_l! z#t_3-eMt_E+l8d+pGhlsoUyWzJ@m}fjfGFou3dVu#_bp>U%?!uGmc+wu2sz0(6`cl zUqS7ECHpO6J==L^KK^mYgsH)+WlQVXwbR*|Zv3b=Z}Ry5v?_z$r@U9VVE1mz3wQ4x z+_Os{<iqR?tzFC(;`YA+r(4=cxF+(Y=7?}*KVrA=-oPDg*Y?A$nAPJ5?=rat#(jl6 zE>mXKGv2X@+4O#)8Gj^KX~Z-0l)gT<b<ILkoVsn6m1qABi<tUswZ^+w{uV`I+}&x5 zn|}W-ojO+~w=`n+zEBRYl!Z&U9+#|L-KXslx_h08*RfN7yxG%AW3_L4e6tC*jk60} z@7#VtBKgjSz?mzQ=KK}%dOh*d>dBt3yqCpkl-)gl-8MyhUa!{vL(98mr|3y@HKwd$ z-Yt2<SH?p$lqJ&h(7S>wn-x!;v+nuCw>Y#wa;FE=%jcpd`pnhVYo540<LlWUA#b+$ z!JE^HM*<p*oFDvMW&HmU>pvOJ?ePr}-CAAe%n#Q4Es3AMXt7hdX{);M3lVXt9;3PS z@r;K!wmIkjU7Gys-*bV;FNY)#t<rVy6#T)k`kyuXt6$YAx0zh{B&N${CQh4is4PM0 z*2&f1uTNgRef|CYyX$^`H1PD<_p_w<>%+IJ@2@k+^m(_xzO?xB^m6&Q<f0jO_V3*F z=L_Q=-kZ-|pI^<duj<eH|LNT_kFBr2-{1e6;a+%%ug~2(8Q!0Yw&}k9UBB<&hmV(6 z$1grrxHK@>e((RUcUNCO>dtbI^Y|ZmrNhU$eGDcBs?6Zqpnu%D?*Bi#PsxlcBIFk} z-aaFeS02E}@@`)8Kfc9XAyZZ?vJQ-$`$Bz6c^&J1E64Tc8&B1@e*OBWeZ#Ig_78nA zX`JuWWgalUcycDfL92iBPQ^|UeXbcLdoKT!y)$j6O!4omJm*}U&x{7f>K<aRg>u3- zKW0D4bwka2*Qx#;?N4)V{Wn)w{?D!}>SMn14|a|3UrjYkWp6BUnEA-#vP)t5LX&^O zz5iVv+h1HA^k@0(^7(c#ad!(&=bwJ|$o^xK&PwTz^GyPm{fv*^dF|Eq)#2;wcRxxi zOaCabGJVHV``Kj-`mwq@jwY*5(u+U)Z{vX)<I>OD>vg6_n+x;J-qmT$lY4ib&w~Ch zDU<Hp>T|kwlllDG^o`ptSIu#_{@399QVZUYcZZkmpP{f)^{WV{)9qZ>?QfUvFH}Fd z@XpPtksBvZFIv3W<(B1-_bgMS^6oUvPTFvK-r=M&8>e^7j`t3iUTU0^ezH#eyCzrB zyw3_&dZ(&Qn$Oi-_@(q*GGi(Klg-EXq+1*)JJ-zcFKz9`%|9ic`=6*}_<wS*{Ihbg zcbz9x>=%BtU-`%VseP5L>regu&Pmh%KbRl+(_bWI;_^@N(&DkNp4SHc^Z#l8^#7Fq z&p-YD@^6RbU;YO_A1(XmKH2ot|Jysv-mICBc=gsKuGxOB+k#5g20&DQv6B8bKd{mK z#Q)0N<p2B{3}^q}dGzNpE7+*?^Z!#F1577=`d|F?|INkqi(c3B{}*SKyIHR>OMzq4 zk;Q-dn|yxOOJC15d0Z|#M`c!Ibk{LSrUSYyecgVy7$xqUE$!a*qNeZ8i-e-reCMhg z<9ckk^@{eq(z7a`tI>S$*Xs8^cNYBdiDza@Wop)c<MXrh;2#Fn!#lcnEZI8ow5xjG zcM~>I#m9*sEH<?^#z$t0?<}$Z_Urf2zuNC!iPs07Ijvv!dqZ>lpR~&Rb{|w_)}IK~ z`?QBix!LxQ0@EU9$Bf1M<fccoANf;v#z8kI#y&)CZGC@<*T?%FTesA8nD_{=&W$d9 z>YFR3&fsxtQb^mIiPQGkyIx(%#PTeby*||`{?|_4=sA0iEli&*IY%j=&gWs+L6beN zkK}FrFnLwqR`Iz##<^b?U3<4hT=tFAY`v~2!f##GyC!>Xc*A|ledV8c=YPw8-tSlc zfBDb*kbnJ8>vLXb@BIGc`v17U^Y>)_*X>^9_4I$(lltfX>X@ePEuXuz(B5&AkO1!m zd5!c#Gagz`5eoR{|Fu5kzx(>)2mg=UmE-$ZA1Y-2rJkW9<p1?kUoYG9h9?@B?EQIR zW_@SVTaSt6+r;(4z4N7t#Lg7STE;0)DA^Dn!GD~$Go-Chq2Hs}qVG%F$G1~{71Vsx z64uk48e-^ocw(TG(HX57eXFxG9tCZfR5&M4bDg}Kmg5DpB{I!{@6GJyC`^4^(SOLW z&c4e{q%Yt2ps$&`R`GOWu{fFhPwVar@h<yazw7_~d;hsh{@3^Yk*{_%+w{-W^=9(_ z!})LitFqquuQlcW<-hVv|G$0vza%isjp^?Hx#oZUkIQBx|6krYN#tVv2H`1;^94d2 z7yXl88*_2lx!H#&<U}9b`bhVFvc!L`#mWv14`h>M;!is<K7J&-=xwC8j1%8}Q{w}5 zdR5Q-YVBV<_}zajXV<+@sddJU3mvUydL$%xZ_z7#S$^%}KAzidg8S|rx-j{KOQno` z)$ezY&t5&w*k{2uzkj#9{hnQWUVXbBKilm^<c?Np`ThHT{k$yy+u%jM%;_^-Ne>rp z{_A&X>%H<Vp|9O$$4Yz<djD#d#jSrrci7GMuP?8Py<OOQwPfbbnZFp0?cDSC`8>g> z33A^LTR)p$`1pa`?*30J{uk#zyS-ZT$7|I;vh3Giw6EltWj`r?w<1sCyO1^S99S>* zziT$!zC6%>ci@?OIqN5?@~+X5do(-sfyCzc5AAnLsxLDCSoJxVv+O5BY0Qo-f3F(- zy;fE7uscv(@|n7tRP3EyJ1QIBryt+ly^F)%)p)L+#nq{|OT!Dy8sz87GYH?%=&0QL z#lF$?gP=}R+#V^5AJ<iRqB<w5wqI*DHeT@e*lmkItr?c-Ty0;sUEkk)O=rgwje46i zo6g*6Vsz-=75@1ukK4JvRpo!L-l^j}e0<SmiI9Wo`5Oz~TyZa->o;W?OIC)RZq-8L z(%+u%(&qS9Jv>t#%g0gsz+NJ;=)}QjgI_#9<~MV1y4}v0akqWC<b?x=b}R{hef3tc z{IBhvHP<&(m*4J<dws9e%-F^$gID7IAAOEz9ZwD%s5MScYnu4}pyY85{`^FXxtx60 zt#-cNf2T{ZJF3O4?dNqv<s94ZF;fy1*Reir;XW+4!e+UF%$bUPU!G~JuUFarTXx$M z_8GtPLUPJH7M)9-xAd9W_CpnpH~Mz&dcQN)V!4DG&pKY#;`#fl>SZ5t`swl5vh?;` zd+QjwsPM(N;?)P=9;tYk(6P{R#@3MfUr*hbMcWU`OurU=K70TC1qMdDoAQ-(_%3kl zO<_p5xLZH5Z<gaK{}*oa6YKjWJdDy-ba3urpTJ)KWs=%%i}`Xs$$vV6`Hn5UTekT3 zJmv*6<}w;AZa5|}qwLMkS7v&@-lfWE?fS1>aK}_`mB^&Gai7%Qyg2wM?|SVHZS&Rz zS6Q_kWcTcz>$K|QWrN6PhdI6<&ik*bog4mN*vD`)Q_sil!x6W49w;l5YSiYH3HZ-& zzxCsp>)(GhpZT<#wSui&aL)T}ALm#L6#Uz>)R_CW%YodGr*}^;OViQX|99nXRipCq zqw4(pwMTbaPgfPNI2~%>e|74G=Sxg{<{rG>VX^$iW3lsog8y~9y3TGrzGBXtk8W=n zj^>#0a(cXWTl;<9<bu@5zU21VMLuUt7oO#Mkeok(<%8`+wmO5r<-ax@yni|ANPpgb zr|V`nO=d~&Fm}-2-(yiYXUkfS)Atf~&Uo6N=v=k`_uXrM)<^HOefXN`{ja}k8GmIh zU~yS+bpEqKC7%mo1`z_MGgmJ7pIpBBpvAtPHuEZL+b-$Jg`AHYnq`@PFuna;W!soI zbM31ciC$H&jrS+B%zOX;$McY#26q`kodW;rU;V#r)&Hg6>_h&~mQUH{`FH(^)w93Z z&(aG1ec$Zs{_L%JYo7Pk?rIQ7s(mMN{@jLzd!FXZ_%67=wDaPZ;s=)Ru2p-6JPBE7 zaB+Px=aL1h6&j)*doY(vvRm9+-G2Jilz>~k5B5ZFbFtdwbAIRj1NH{XSwgxFN=M$j z@N-*3^!$?ZRr7531&F3Dk?K3WtLx<EO>1_o(X?V(eS2DlhgiO6SKUVI_ZO`WS3O8v ztUhHHbBCW?*|{dU?8Dy4FYo+5`1thqgvAea7x_$L^*U-6eRI8;S)BdCeR&=$6HE?h zeA}fFQED>nF5~C;h4%9In<nmf`hG{o;*GO(tN!-R{o$XXWF`Ib{6&%U%Y|Qdeo6WI z>vosN9L=Av<h7G;F^lqFWBvO5?60hUmGA23`X~JQ^eZ?%t;6Ywj#cBu1ILy0<z%L- z&bYcZQ^(3FQ0(T~r<-GyCT%*{RX($#o#lJJ_~es3Yu257!c@O8F8V{>djC{rt^dJ4 z|5u*+ucfas%japm*8lwUNf|!>ri+A5+4yID)+QE~`VGnrYKkHM>dQXayIpSBId5Ue zv)9%hMSXeh`wtr^e&DGQNZrErslL_rFvBx}J-?nc&U2~XAEhgwFiV)5bKk|Y_j@$A zXcxSB@qWMJ$>+WDGc;Bv#)wRq7?gVTR{w*P=_k3A_o_#3=X~p)a#N18$uKE3?m}dw zDetu{qP?X&jpi=LpXmD9Z74plyX}60(edl{#!Tlqnbc)}9Gk75n050dOTA6A{OxBh z57e6sEWdngme)HjuEElpD_0@z_b);~HPZ5e0>=i!CP^vr;0LLpax>Q`-B!}RJ?q3P zWzRHszV|D(>Gb)mJYlDM^ZXs=5|;i2H#52{&g*|HO`G6VGkwQxky%r|h)SOIx$whN zX#KPwSB#hSv8Hk4c<f|9-y*!XWXB6LamJ^n|2F$fX5uf&XbKb4vyl>fw?F6dqqxP# zRZlg?AAF$Czb`hmV6mVR=f>{(r|v4*m;XP%AUfHK#V=0WB=~|%*v8NeMY*?AOK*lo zhF@@7rzX88*Fv>wlVSD4q%0dZ?$7Jr+lA<IsQz9T+BBDM-sB$@M>psF-25=T_{Ev_ z`+pKDF7DShEH^lAe8wiOOe*PK^D;+~QeVlBRtp4oaV>Ma8gX}PYFMcIF76}Z_hdU$ zmOXs->hRaq@!98GUNjWWHnWplR?ffT_l7LnIE$ahPsLk(`_XI2JNMPn1(Sm+_H+hc zTh8zFJu_3RVW&!#)EUj>Sh0i!lD5~D{c~Hf;`*%<oA=EOo_kw_b3<`zdGpgU?Y^u3 zxD9XT9mzSG_R8T*`6Y(ix`nz7zdtNHw>R1U+U3TzF0<F=+1`%TIcOG=c;>|G4Bzc3 z!O8E=%ct8#FzwuRxmR?<(!F<<KGWr@aC(u$USBP6jYXzN%_fN9c}~fu%S~7J|4xs4 z_OtElQ)`XFSx=hWLV{=7+gjZb)3p<=s$rQ`BeH8xyP5lG)74EkN+XIhwt6k!5T&{+ z>Sb2#z160xrPl0<dKw(D)+lyu$yU4fS7+HWuh<p!H8^6e6<Fl+)mgS_tGC76HvFcw zA;oo9<x=l&JN0iKI@UJRRa(+8X+fKC`nCwWN!IN8DGO#^{d51CS!D08q7xZkzr9;< zHp@n9N$%9`YHHanj;CT8R;C#qxMCvJV7z6P^ZxBg>f1D%8<za$4V<#-`R~`v`(8c& z^ZN1LE16~gA3W!G`@!(zjK`JS>XaV0O$I`__srZjz4BU>WZkFG)s)S>imO2J#5E5C z_jT{Oc0JnFq?NVloyH&6GTl2@<Cgf&m?a*w-L>cJ<JQ}YX8z<m*!<$$zXJgilUdG2 zIR$E~XFYXUJLlU+)~u&fnC-wEt(>6#oTpQiRd~8jeA}(F@PtR?-j=K4_i_X#pN_I9 zU1|7=citI+`7N(@eSOm+b5M8lxg{L_i9xG6A0{lcKKn!E%`DLv<<3scM`5#<yS?4D z@4oNKz}?FPOMc&Z7VxF$anRIxtC%0(-LqA6C*%5@DXt}ATIX3Lx#!H0oHFkMkJtGe zHtmSiCubJ?X-NyHOEZpeoONT?!7>)ENo!v33=DF5<nFuqbI+WurVLwuMV&kHYl?Et zg&+JT|CoFKJ3O|3a;&~#mFs1Wxw9A_d^=Vzpu)K3d(IzrM`rQf{~yjgvftBp!6f4U zw^N(u7|0m>Q1AODVBdYnp@!@FMa6=Ew!4PPCyun=;Q2K{UP{Tl>&W~tzYi6gzclZ7 zBdz}9QRIScKksY|(s%p5IZ)+M-*lcV@%0y#Z=638Dr_`A^81o?Uww>JcC#s;7gJ;2 zllxPm^{a8N=X8;|rmU`MsjgcigSWd}GvaX#;ElYvWRJ6u&Wyv)p591roXa)Makp}) zROB9=ja>@bYjUiVuT78%=wJDAm)?v$iYqKx6&$Zc^<CFq8otLs?WTFcuWM&Fa-E!) zzqrna=kliFTaQ{NA3Zgv>RR7qmk%=TGyL{XtJI$PYj@Z}?>j4&7|i0I7pqc`7aclJ zN>$10!=dJo+p|<8jZep)oqjg>DEo%`TXI|3x2)zmet&m;s(zw#!ZXFj=ezAsByfL! zCveE2)m5;~eYNbIr~HwJ9Zt&{CKXs8C`b~U{8UfW^0eQ&CJQg)HwyyenA08}oN?b; zaQ?}y8G0wWzkOU7BRA!;uSRm8c~5fj(x$F!n<5YYv6l)~H;{0A@agPlb1S)-T2J=w z$h<gf^~=?nVr44?Gn?1yy_kIBZ4v8<h$ZhPu>8vXup@Dz>Wz*>mpe`OW_5`y<5=R- zEp~40s(y=?#@dG#&#V5%a{QR)dAnOCek;v+KXv*!ms!UbO7*FxhtK3H`gp|C|L8P} z&>Ax(eKW1Fz>Qs9q5d9gynY_e%ZhmAes%MPbCvDZYbKVq-Bs{xpOd+L-!n6hfc*7B z>+gj=)R<Kwyh;0aLxd#1T6^&2hmJ4h6&|j26S}?9Um+v2Q00t_u+Hy*N!c#pb02S) zI+dj!qrx>k?O{;q^)0;OKUp3q1@AE7p1x}L?%W+O)EUI*9$Ff?BS+>$`0?&T-R{S` zoe~!Nf7~Rl|MQzvX@c@xhMW}wm-%wCnwEa;2(@NV4zjvzlE9JW#((34z2V2{Dps?O zJ2cKbw^3Nf?)vK1xiequ$Gw<&@5=4ur|zPULKOW(AE_@9h!3@TEUo5UyZoQc{IID{ zpF9<PynE#(GnP~HRfINa>aIE%CvKPUA-z?zfcsaD(2dOCzp-qROD+VmD6$3y-Q}&( z_gS)>eR7+Sg-!U8kOJ%b-4Z`vD!MJ}&}^Q;mG`b%;Br&hB$K3BVQF^!GoHLwetp=r zs;Xe3MvT`>#n(+sRC84_7j%Ri(PfyD)u&f|!O1A-_&h~5(^*eNs+*maqm>^%N=x5p z{$gd;cb>~;cPFmf*th8Qnl~D3*&cf5v$|IFyKPGT(B!bSI%K!|*6QCk#iOEKd6SO{ z8~2=5jXb;JUxKk(E2n?pT=^`6=Qo*`W$bj#`1bM@bMhA1V9_1SDk`o^tP&KL|LQ)d zV5@21A;ROE@iocdgg+OL5v#K>mo-n@<*QepHZIIHy?dE~*>P(O57$f2#->f(Y*X?j zxR$RiKi%By;d=5|NREW?+M7S-&XCxc{VqC)S;*m_<J1I48JAVdlBy2MwE8NaI=IU5 zwN&VT)1|kpT}>~YiIn=#{ZMEbo0iz@HlNmbo9EgOBP`mLW<1yD6slTo<ycatbLDa< zTW;dAw{zrNpHDmzGb#AB%V(~_|5Mb&buYZP=i|t6$z(bj%xN=s-MkMBb0^GuyhrH5 zkJOhfE-zgitsFm=H29tHpX_(yd|@1?M)T$pr)4FJ6y`3dxYfP<vTf`QZ}kp2<2mQ{ z2-&E6T<%skIqAMkTqL~pW!o2%mu+8qo=+Fqx?uN&MOT^@W%AGR`<+sxKUZMBy1YX1 zu^DP&{yBa9J_Z_V_zth~JU<~r=T*t>w%2ZINqZWNZiw0}IQsHk)#>A{#(qKf3+30v z?X@ci;Jp}hUHve7Eb9rYxl5#+Z7O=7UF%TmsOjq6@u@_}*<|uxrUJ{GYot$3F_~S{ zd}T{W_>O1(-G8<$bG3V$xpKk%Q?sW{K6h%Oz3G$5#RBtYW$mfc=8%0_w^Q)bDTVZi zHQLs0D||Xuh$Xo^WnLnwzA?!m>&Vm`hJ|MjvVG}ZJ7KYkV+Mb#`<bm9gp*X>Hg#WK z^VnkXTZg-X$t`xVZ{E5@L_2b58JxImoN~{Ted*_ei(FnNoUWT;9jHE^|5ZxYu4%G% z<qO_v>{RY+-Zd>a#K!*0Rg0VVJMCW9TyVF{-L1FA+Ms-kkJ#~pb3Mv;Eq|cxJ#~U< z-%idootOK9>dT}~$ew;&GWR-%!-pAy>sI_L<bSrL_~0BD!}2FHqTjx(@?$MFI(lcK zbM@BcFD-e`Y?T%3c~!}k;BO`VCQz>Wjzj9(tV%!TQl-1Tb0+jXzrws|?t+f(!bw-= zEM)n-b?(Ywr{^9#9Xsyj7G1EjxZUF$KcVcI|EWxuCHgG$pOqFZ@0`CZw8XX1anedT z_mA6zBQDKk@?La6X;JKLPMx1VjjF*3f`JR)GK78B+H#pC?6TBWb*?p1Rh#BAOg<-) zFhzAzK-=4fQ0r40g72~g8P1z=ESr7btxFZQ@f)+%`)&m_Y+b$WRfV3hqvHp4;WV2x zJ+;X*AD&g8%>CzR);ryY5=9^K*59vmT)%nG4n^}nhpQjo*6&NSb~G;i@Z;9k$<JL) zf6CqyuLztFXK??PM1!b;3FC@?KF{MtX5PHS+!KC*VX7!gsIcX{pytgx3+htB9+>pW zJGBY$eLN}sfWINyG4FAe-vM2@*K6xTr#<v{4F2)O|HEvR%uPR>CYZVkvp7yWP&;vY z%3IdM+jssew3>PMy=>J#7ybNgADW*=$uJZ#@0%#7W-V*}A)V(K*L03hpD#s4>YtSa zBrU679?y?mf6>I_FCRZM`<dR4M?LR;o)%p2S;)%n$Ia~@C+}C3RNMLY7U$Xn(GDv! zHm^CeIKKDi-%~s8uljH{EAMdH!QJw6R&FeLQ<7a+8qI%!H{{(l<vXk2auspK{}#$A zf6aFCzz!V~iIr;W+0#EeR(&Yi)$#g(e{t02pEu`C?2X!B`ZOYfRleopnRI^>HtDVx z2iyJ?Oi+J*jQ9L?4qhYap9jC)<GyNXJZ-_U@c09KTx<d@>lG&~Hg7nQ<J<URj?_Q@ zguoh>^VQjjlK)CMzi}nJp8A?|s(?>X`k@<zs+poCmOBeV9fd_a(|IGAt2-vH*t~1y z>@^E#ZBnytT6*)+!dkA6z5HB?oZQ7Cfmd<^)22?$*|6zJk3-_RQ@19qi56P#u`W+m zi|6@0Cx#g|R&EUbv!5#6Z{hbdcvtu5$RAdLCGQ&bCxkkc-7Ko#x9`{K#`DVrWhIZZ zwC=8|&e$@!RirP!SX^ROWOd4|X?mV(R%wW7H&-T>&Yd1{yi6rlMp8(BwrKf+-M5(C zxEm&VZe4PFzqLuhgi|S2O)vP^mS^wSbvSyBYNpwXrbQc;t?j!Zn16GZUc@?$=+NB_ zuX?3=vTW{zhzIWTi8eGm^7!oSYaQY_*NS|5r~1Y*YkNM4ym*Z#{E}|$gf*`o_rC6% zbaC&`)3Xn+<u&m2n<#YQ)8VW66N|1`iuUYHmXgZ;#Ktf=^W>U$pR87Ubv?4Wc0!KR zYwNjM!)4kRR2!eO1WuZ|Ffr<`7b~lvu<ZMk^>?0rJ-&LjSL@=Zb5GCNdHwx5{&TIZ zmNGLMI<7Btyvo3MIrn<1t}EM?>z72!RJ0h(#00W(*$?dQ>eE=I-E?ZH;0!+j8@?I! z-<{7_SoBD*(U*SC$$#g!zy1HJ+Rvx2DmH6Rxi&E*?pR%<{ymnDyPX>I*scppnc90< z%05ckp{wVA<irXV;jWc=>&{%)c9Z@*BPB2|y662`&b)m*x3pbEieEn9+ql)eM{29f z^j85Z)+lUrk9$8g{i8HXe)Ns^vMRx)n=<pfFRo=fb6P+_sV%GYg#V{n!CjYa-YUA* zXC+mn&n$frrF>((>~a0gd`l)runWbqm&k@hvtNC@BlTKijnHd{Wv?67HD|qEP?fUt zidBZ`iaX~@18!zbT*thN@73{Lr`NE*RJq1Hwf{xcitTc*)-+vXe*ZRxQ|YeZ<*5Os zs#m<cCPne76!+V5U)9ePxXLIH_~DAr<7t-+AKP@a@W0QOw%Ds)U*rGn&%R5Hb*;jG zR=NKOJ@>)?oxuKgn*aVK*9d8-R`k_hY5v2d{xh`yQ}*1aldWgu|6p13>|)L8^v_%Q zpLfnVCu}!wzxGVN{NEM-#0s`Y|I;gWsW(rMo1pDz@vn~Y@Lrv1;`%eWlQ(wEJSb3C z{c&+v)cGr2S!e6pb;?yvpU!Gncdqj7vNs~@&IsI5(zO+Ic=fq8)#TX*u{ssbW!zd9 za-{|Aua@4Js2bHE)^tksq9Kd#ZUxKx8vN#S-<d6!=C@pPWQt3txw{s3i(%)~uYwZ{ zD;*P6uWy(tsQ-GEp3vM}7Y1>+gfl|&r+!JlKHI3{p0<5kL+0dnm#X(?=$hU;{wjN# zi@srt)ccgwC6itx&(@rCQeODIZ1^P2X`7vw%{w$<WiIc{ZO$G`6SJ+gzsgPBedF4N zt6a}KYg1PA^L(9{8MM<4%B*y=Gg_Vd%wEUIq3hSh4&C1ub3B>$P6@c6P@0oG+0U<4 zd~?6d{U6WHr=OU6Yr=MGh1yly+hw1%a%Mc<(s@HtWM}Zox7y}WPKRx_W`<Qy*}Ngm z?*!k;>r<cqVL7+gb6(^7$(bBIfl)d^i4V*-$lRE?+QHFr<IRaFJJ&4e_X!ji^$e+8 z^!W0M-S@t=?K}Hs($mz1oAhc+Tjtpw>wVj8e|EOzygdxT!9|%aDJwNs&zUtL$lpp) zVcMJ~n@ckkF0Ep53iz@@xp>Z`4UPe)JdSi<o+uLaIrp5f)Dm@N6OWLL1y0POQY$Vv zw6bZL1T0**)<K}ssrgSz3)@UCUR2pFqNeH585xRMe2NPlGjFIhqbO*5u5EIK!*H6q zjfcNm#e(A^Ar%V_F^kHr_~6jWu4S`Dq`xpaB|}qAS#hJ|619mTISZ1QMWt8Va5&1Q zWoD4ew*KxkSr4}LwoUt=PW<tDWu@=6vKcui!Z&T3{p4k($F<Tvl}F;0QhF14tDLvJ z;qbh|zG>d?$C;IOLZwwUuJ59|{$K0(FDn=!HLasfRm;shBVy6PjY>SWy#bET#lAl; zc=}YC`C@>*YU$3y9S!rcPR!3Wi_YYaQjc-uTdpp?zF||<saKk-m#>)zV)%Dm4L=tf z-}Cml;kP>r*PVa6`nb%Ar+<W={+aSQ_?*9`J&0lNe@@?4|6IIcfrH-j>6*`%&zWCT zcj_mI@xQXD?q_A;KdyWKE$7Ui^Bb%lu5rG|^KcFoMjOp@@rPUO!<iOD)oU>Za5i`` zgfJ}-I$%7NVM)3s<CRChQ)EACzF)p){-?TAzd?-uN6!43KXYxoY5Ff2#)c*4wuRws zMfbX8&!?(oF#4*UsW=nkqh@?~w!fPAkGEIvL?60W0B%@p{Qjuz&IkVYz4`ks*c1-x zOYN+vdHd_+=S8#r@V)2Wqv4@HBVRviM_2+Q>w;h6&nr8XjH9a(c5=@;vwF{h45Q=a zaTi|u=-uX-(|Vq3&ascq9%hFW`8=3boH#Pu(Xr~IN5bFLn|SKE9Hcz{Ke_mx=|8Ah z5o{VciBVVJz_qsegCBC&)t|XgzQ6p%PvO0LZXV*Fmc5K|2lu{-H~Gu0@*bR*=n>UR zY=br{CX`!%n-$I`iW9jF470grNbdW}d4+eo%wE&yP4%%&wFVC^M4qdA@3MeL{ant* z8kOg(_InpGn;x4ay~cdn;k@^JTv3|xCwhKN__DD4!0eCT^0pf%XQ^<sYwz%V#_9QO zR~DzTuW5wuHI=Ywv9o14n+|d9N?oCMgSmTKO~LPO)l)MCE81!+HveJGdH&$v3nu}K zMr)Zq_MWbdv-FPV_h?G2+#My%&GvBG{?i;cbI*KT_FOAcv;S0m$Ukj`|0kOkWGPMk zzv55()BP*cEgNL6PG#UfQNKvb?bCb(j!i7r_b>C}n)-j<%s=0?-7a6#j`+*C^~1_f zo3iF_Js>ePFes&`poV3k;i{PvZb*DzyzapcIsQwFl1*$iYj5nRt~~kg&-^uKJ_giF zRXl!oxM(LwJYTzq_?y~7oq987-KT#Z*vYLg$gtx(sDAh_*S9yFC!3p1FD>wRCN%xz zo+v%$^Dzg_XROFMHpB1ldc_xV+0}`kZp^s-;U3qXhr4?O_vabM|9xQ092e2VrBk0* z{o?D>=8Z?TZ}6J^(dk%(4pTj2%AKXgwJrPycK4kv_3mCWdxN6h6fxIJ_ZqY$HMR=B zw#n}}#kS3I3FCchr&Q6)xhFq{{9FFX{_6ir-7Egs7atPP($C6c;Copw>Ui>1z3aU2 z75~2PJo$frqRG{ue{LN)@e}&B)KpF!=YH*Cdf=ju;@9<zy5~)%r<X>HMOLQtL|hK_ z31eeA>>+4+_u*WNvfr)d<$t>`U3&NIhS2n~Zocmur)+TFv*M5Y)BRKag^RFg{SW-9 zKk5IUpO@zU`rd!`RQ;kAr#AizpW-5TvVNAw)BWjc|MzxZm}1J<@qU^Ji*iQQ@qkyy zPB%?3m{GEHoy80(kxNR6X`dz}yogx!_=EC9(@<fKwr#66EYss$^MY&Ek{yc{X;ukt zu2><wufgi!^urIYuaDnZQ4)DSRZ-08$LTYMhe97H$Qnv8){91*yD)#_qYWOS-3JQy z=0E1H4}0>qAd%(&jHKiyruFRGtp7=@nUfSdSBIzJT|(UQ(|6vVI(;L0hN@nQc>71m zuA87>{QvUw|6L0{&2j<F7bO3b_uxF3eE8e`CWV8h{7>pbAEX8bvZVZ99q_x~>}mZB zd7(*-5r5i^oR;6X$Kd&gJ2_7}`*-j4W0xv~8S4Df9)D2hIL!Eu(RMG}nOl|GyM9ZZ zC@(J2vro8JaapzG(Vacb`)g!(-r$?DU-9N6p$=V#RT1LTCHA}R=bzEvX31)QVD>{J zhWC1h89&>7NOSw}L;hUy7n@&CF3n$;_W6wbj(a=ID$)<^iMC)gk<v)up3GZrcY~wV z>;^}dRPS+KjoY4aGbFt~++3~SW`4Bx;9Ae>F#c`*Ti7e*JYUyJuS$QvO!w_Y9+qPj zPlTs$<cd3Y<0s#>DVums7QZm|kycxCIl}#7X;_&^v#HATbW_(W?#ed}86KW2ec|1; zRl#J9s;2)z$6NPbg9gneimS}~7gEn~<iYXFo|kTSCPtP0nkrDeGg3O5zrcQr+?<&c z|5tD>x0kuEbYfAgjQ*=_%RKd7zfzt&wX!>%H<)Giu8Eo}CMBI-xAV54Omyk}AI9wZ zO>^~^@s{dssQ&oxd#B~0^y8nDSaRp;e81*<#kM4U^C8caC+}`lm-jbZS~tg2?~VDk zh5xc%o_()Af9`RKAQ`7~RXPi=8*Sg-6T9M8Rkr*wvp=1}t1SHj13U~AgeC9aoBFkg z?aGCZ@1Ad19BRj|yWKAQXF;Q<oz#QdE&mpWsxT;cF}>f^m&#PLqKPMLqVlFmD_1uu zSU1^B>Qp`M@<CQTX1Tk;%e34{0h%8eUv3azs<&s`Jw`wA63=P79go&N5?#{yD%!!L z!)%{M?W%|h##4bCpFCQ!@)YaLW?Msf?oBOrD|hLtSo8%yQhgb!&)KHrx$IP5&h6CH zlVOpEgLpUm$Z@`Cdisj#)EB#)Q*w&7u^ivrDa4%oN>Z`XXu{IOmfJl!Zj*e4zJLBI zzy5yRoA2*`?Ow|H!|1`iAFJgGA0%mh{8jppKOu)_-;2{{AFf+?bc>>Gb=gO@r{{7X zRvkWBV>;Jw!b-ab4mUP_esEngq(|iTMb+dZeJVGTQcq8fygM!Bn(W8E%-6FPe@YGf zs5$AKccQa}c+Q$redpAi{{4A%_^JMSyDQBn7WTitB-pkl;=A#=tVV$b&>R;N!-O;3 zRz1I1HM-VjtV!nBqiCg;pV{hC<zrdjJn#Ja`m}!;K64KwY=|!wOxoqxsLcP$Dc<Sr z)r!M2Z;Mn!PCfWUdlN5zuIa?92e}eqGgzMMkG%0R&tHDIT%4!xMCa5~9kK@(-nibM zWW2Dj;p4Bgjh@L*9WCyhRGRByZuH%90gLbstFpI2e?6)><{j^HkvV?m0^`FAj8_X( zq`!DG+FYFE*3fZc*;}i&wO&Wd7j6^RTXrmY%dYkJ#r_Gjduo4feH*=cCUcm=HU6Xj z5-(a5PqUY<GiyIr^Wto~_=hQ0**_a(Hq7zdVdR|ddFR7J>nT-nMu!?+9#i4_bF;K| z|L^1jF8)V*moF16sZZ&Dk!yabQR%1!yXgMO2R1VFb5sZ1K6lXghrqmE@g7aK^WW}< zurxm`FS*c{yshF}|Bog1rRKtxYc{JNxYbvXH2do@8|_tA|B6?C`^v1u8}TD?q8N{% z!lSmFo{xGtb_<F>6#UuyJN%oJUv7BA=Q+7kFBE<H!gHuvRE0G_`T?uWi}vsL&qX{q zeKD-UfQ2n#o5b<sE-`<+`HwQRu4evoeEGlV{ha@Q=5Nq_80NkDNtuMKeV;jBMODP# zP?yQkb<MmQT0%uLUFPgm4&2r4x8T_J+3CTyDlDqcgYU%G?fg~XTGYSQdvbu=wDrq0 zJ1v4W{Q_QgN%;9obkv@ZD~pnMY`g94v4OdF;-PtOm-S5i_E~J^^XL!xOI`MI1gcMZ zyo+z9-@f(!^R1UV^GhqWEO%g(R<G5)u;=fQbyZzoe4W$-oysS*_$_Mb6SDGpu`0dg zo=S<4YKgk%ixjUH8VeV<tgB+W!|SA;G3CNsrG>&K5J5eq66t5JMK$Ig;+}G8uENq_ zE}7W@UhbNACEv!H|0&WEv|hEs+BeBvv~<diz@%`?&g^Mtwu;Bhn6zut62B$w>!(}^ z3<@_+Pn~v8^`+KIOJ&u4#|_hMGR{{#3hTa7^+7Y}<F}4V#aVIZt3JrxTx^~=tuLYX z@CVLq+OwW@h{iakq{f;>Y<MCXwk758#+<`fzE_oO5qit8?bgPCSyS13J3cnOzZdhj zs`Tf?k8hT=o|(=6zAkx^>G=h%OmT_p?i*!1+s)oJ_sqg=X<RQR`0iud(sTV{?hgCf zUB5oe-+f<A^Wmd?wh|8y@5q+!dc8`kp?A?rWzP#N?j^COH@Zj|9WA^vaZO)EbU}sZ zRF%_W?yFXRUX`|bmxlDW41e~6Op(6R18p~HWgF#7ty1V(w1|5W=dHZ1RoWhtmSyf) zc6!%JjlNYKizgai(mg3VbJNmOtN0jlPgTEa?0b5FQ9b4uUn2W$llZef8yLP>pHq9; zb7)S&{B|e(bu+6bp6t5uXTyn2_e_O$&U}=8v@EBpc&gHl88KqZa!NmoZ_WBpp<*Mj zQNe~y?N#H#UA+-(5}$T5INKQ~glt%OlEK+lJYmIicf(b4&MZB!a1OV1;JLoJQ|wN9 z99;BPrqjKZZD&Z2KdaPLll>do3*@gkXf=C0uMQ7mjE>=rH2&&%<vmw$wEMew-8ave z*aFV-Ts;$T_DtN_GyfLU_-dz#t-c&|Mj&bF&lIzTEFW6*OBeN>`|>NMO(d^fWKB^< z@U*FU-|d~a`W`v=oHKvFr`{z+@MD{LyY!?h8%*YXd$4?0{TH=qONtLpa@n{=+*|ZY z_w0yC=UKgtj$Vq>3BBNvm$0%>e}C}7pwR6*Hy;cVbzh}3V@h#i5m#yv`+<<Cmor_1 ztgFroJ5H{6_NY8hlU*>(w|rJ>WRmG@?k&BQH)b{Wlo?qc;$1cGWKaG>#r`&H_07R$ z27DT;JXf#i%=En-G<(}3^IWgOTTRclEO|90=f~%1Q<ksI^!JwBHZ^ELURJ<t8!e@I zg+DBoyJs5R$eOd~+oGeUW|zMDY?>4}-M{L})5|hnyT18-T%oPrTlzF)W8BF&6}ivX z{>Eun)ORhne0R0iP^nX9X`+Sp_uXq5vntGcz0L_%f0DVwF=PE=$+ugl{_dWkSZ%vs zxh3gGKllD+70W8@%;s(E$lV?DBjLcA8-?y4@B8XCmmT^(pX-&!Y!(^DDwj1z+A`nr zncc0TA9$p5&#CHj7A$zOnYFKG+kutOBU&03&(S>^cy7j{D<5?oH)Q(97j#`vd|UWw z$^vJ%yNN$nTNd_nY!q0Luw>R`$55-BbE-1J8*+K4Gv3<yS7B@E;l+2e%_V<M{PQ~a zMOK}7Sx`V$jr29W9=}v?v1CuHcpXm>@07Ak!)Z@GAD!g0(IxG1+r}kx^kaiGVwE;e zKkSi}?q0qrBP+%GJIlq8it6hhW73Qo)pI9v8p|1rPd<6(!?VdJS^p)OexFvrVp*~M z`uhUsydUk~k8O{?(D&R`S-gLJtbJu%$mIJEYa7K`U$TCF>&ktd>wqr9)%_Ody+vk9 zZgG?4mYTrC;&|1i@BN+y*Js9TleFNTFKW^IxP5{_i*rsS|BE9k4ii@vn%qB{y!Pw* zQ$~L@Gq~peJGuCN<;zxu>@GEqCY{FLO6xmraku3c|4p9!9%-mp^>O>$7u#nzmOPS{ z{JH3I<1$GeH{R(6k!n?zJDDRUnzHI>mcAC&_@(?~_4YKU59_@TG&TBc7UYvP*qypz z)3mw`!LmCQxqc`<KeNB0(SHBix*fZIT2y}hS5;J8`t#-C(C>Yc#<3ZW7v9PQTq-S_ zDW{Ug)wh*vTS@FoHvPZn&&`=5_O)P+dPYpJl9GR%!Fyi*#dE$-6k*Ngs%D?kw4%fD zPh`xeXC1Y*A9`noD_r^O#$T2hURe3lxI)&+_{Tjx*VHRhqIf-w!guWBXM2!T-~GYk z==-#i6{)T}qF&Dj_3jpblArp&=&AjaZ=vp=v=#nyuF~Oh3i~H)(z*Oo{OnKhZ)Qqx z*9J_{&=6E=EJ!?)tFXsKf6ZAF?~d-5;*CCsZ+hF;y;g2{*s#;(r^^NT=^nS3-sDR* z{nk)t{j;-Fc$eHF_JGc&KaT7?Q=AsZ|8M)Dsr4}}Q)h3%%gERH*UQ<?{5~*S^5Elo zi~f&?S1^3ZjLCabWR+0Ic>m|Y$G@hp)?d)RK{tBukyo<(TWsFte9Ot%P`J<V#)ZJ< z{Ra)w^B(v;wfMm|V|Bi_#uA@=xx-71yYrTbPJO-qz=X51+FxHzW6ILKzt~Vi`PSnt z1|8epi0s_()WK-a3DX(krO}sFrk8%5c=FVqqnq0_yVh75v4#fa+%#R=y{*P);~Mtr zo!h<Cw=nUaHK>#Po_SxLVSmOXwH<9w8>JTP-)w6r-(6+-zSQV1(_Ej%B{dpu@<kr8 zGlS1-eMri%wJ=uxTerXQ0lz_akZ7yvp~O9vS`xF@2mD*&Y`t#L%6DaIVNSa1r-ZMR zDDz%m>DdsX_wXWH&!>w)t6a1bnI6})U3`6gW9G?#^<qw3*IG>lKTqB@Q_7#?Q15{q zk{aR7#ihctc{9BIxo@#JTjVP5GK=d>F<9OF^P8Ac_v+?1lU62pZrPafWck*VlvBLt zTBJh^a&9$j`?qDm+Te`&+*>yP>i={jtm30)V)V)^LD!9cpKO@BzGpR4;mb_Nm_-8i z`W@jcW!{aco=wq9yk=}>EH_<#hUXCfku9}ppT6tep0`+OYhkSC<Wmz*-LREVtmv0! zo~8ci<{OXa)@SDYx#E-3UhQKiq<P><-1l1<OFY}ZD%E_53agHMcxB2T#{8*=Zxp33 z-p%j9U+ePjg8Ba^+g)TH{L=2Ph<UI~?6G6|_YBi{c}72%_4#%5RofoF_f_VEe-_`9 z$#a^!_%>dYnNzmw@t?CZD<*vou-$dK&Ukg#C&ov|R8*Rsj2tU78<xlf_%UT@{&wLE z)-~9!&2GMrTYA5~<eL3aRiA&KOlRj1n>bO4=~9&qYv81v%u7W?>%F+_X7>7Iecv>z zT43MQviNoK7We+jl<kOOT=4hW^Q`%L8+<jT-rPQNKxC~JBSWxI#q?4gVFfqQlntw7 zCQkK<6=k_8_++Bb2^NMxlO1!8Y0jJ<aWZ3`XRd<RyX*ZaOC~Dj-YriMmMu9sZO&4U z*!_)KmsGwxFip(*)pw|E+1IO@OHSvV%3J#A-a7wvWou4IE!VkoGMLHJK*ZB1v@GSe zp0@Y4Q&Q8i8lGlIcdd(Dwr*uhxRO|7!qfAUj#QXEJeu!gtDKW`GySF5$Fjve!JYTn zk-8|qmvniQckh2~$`Ghy9=BibBd5*bhu!<{sqjrc>O7-8|HRdKvC9H?8pkerS6~$H zyIeTg>g)bvl3TY;_2YeG-o8x5Yma46WF&J->@|0@)t{RVd96#-R*t(C8hdA}UQw*b ztL#%z8`6CPLYDkb`BJcaUE69_Rwb@I!47V@B?1@3=Iz=vK_MumYl@ZC+2so^skBWy zb?U<NmT6hD!Vk=w+ibV)$b+VAYoR2qhGl)K!700@$USho5F%w=&2VAQ><5~P4>ID~ zavhsRGFLuWw4G7=<(dT5zz9<n&in&jcG?jqMZ$PH&q_v^zE3Om+F&(n`nlldP+sxr zycM45too;TP9IpUwBpvyxAU)k>*ac%`;zrm(c22KM`3OguW)&tNL;#2`{)zK;}ezh zp35Iy{@T*O;ckU-lx+FmZ_i#G{#U$p>3)-C$%X%|@9}IoJwx|c;S5K;e@oRrEwX9& zdH7&`&8z)iXMdRg|J!rE?NL#Gh00#KY>E^){@-BMqW{8G|KIko&bvRAeUD=CcL^n3 zw&j+m7RK!nnirs#zeyoWZGOya39Cs=y8IqOtU`(M6PB|riE2O2IU$8h<xroFKd;Bu zbJLO)G^Z#{^ilq<(ioyy9V6!EuOnVj9H8{(%GWCkLavwdq@GdU`|%Io+4}fHzVYVQ zgc|L4uX|r!&okr2${im?mQDRR@h;;nJ&j!1ym`$Juc|jD|76V2x|3H}&@8%W&)vV1 zkACj6>B!h!u|QbVtn01H*7Ys-vr4C2*Ap<cKF)Td@>Ex>blenwEylIX-}fh;FAM&C z|KGo-9RCX+9xq9})Oz#KA)5ueH^%DK7$mIfRq>Ykv-_av2b-_<twp7uc_UM|aUGa^ zfzj1t(m7F2Ay*+q)qob2pD`0vf>i`BF)6BOKKGg|;x(CLWurjfy!Cu57^cno9A7yp zLTM5EraxC}JgY8iiaFhEPQJ06X*2s2U2~cG_y4BuZE<EQJNVGZ!TO+l%eJP9HMf1u zF1PJlw(8n4|6>gbtdF04pRl~;rkMG};|=d#=4d1rc&2mfbvCVDX`9BQ_cQ09YH)$+ z*0)C<1f82!q&cO?bgS^u3t8#*RjWQ^RXG2e^3b)Q*y{WAALd^k#Oz$+H*s43meu(d z?{1t;-cgb!x_Q%tt(`Y#PkyTMa>fO>p8mCh`FsUuU)UxTAHTnQ<J2Sje=kh8DPi}y zzN6hdh4oL>`!l)f4gKlIuDtyBLcS%|+w=JR$=8}D6eo2z<b+9v^Ug?_qFUK7?VQ*J zA=WRRjJxvqK1_SV;3s~;2*Q2#e%cv9KhX<ZOE0Liy{O_$j^5H`ardtD)J6W>msl<x zQHt3<OZ%Ip;On_N)1r;PWZwGFBoVgym{Fwen`>9oSF2}Fb91QPX8Pdy0$c3}lT+VC ztF3ZZ-r2VBR@13mSJS-XtRG*V<WlXr&tf7O8hg)a!nsmKj}k?j{?-7;qtmwwJSmRl zFpA|kpR5=Xz?-Mf@-)V>$;t9iaU{pm(5~C37pP8s)RiUjGAN@+Q-CA;PG6BaS60ow zUvt+Q+ROeu$N2Y@SyYtw1eZ{q<3|JqbtVSpK1mF)O6KtrY5r;uVg5SEJE}GK*a9EJ z2>#~MV3Vy|7TU-1Xied}b~Isci?!~%rT&%7j;e=dX{c=N&9!trUz~K>TKJod^z2zo z7Ai@)$v-b&&GEB(aZXihD|@?piE7=F21moxvni=@vW*V~-PdG)>e9HqZFSVMeGeO1 zQsV<+ed^c6zt?WokUMd9kNNR?O~QBB&)<uF`}mOL<3iV$lk4{Vd;Ilw?aRqJ^?Zp; z`yB1-`D~868XxN3wKj9o>0Q4#&UK)*5iT{vvflggC~;@Z9vQye;)gfp9sGIlZ$aW6 z>%-m++pFbuo_udiuH??|6o}r%XXA6z=vOsY<k`JXe+d6rzH#63>c3xKhre6>{bqB5 zb8LHd@lT6ClNDYlyIxIQ>vC|%>R^5bl@u|*11<j}BpVN(VOYxjt?U-J`sb@9R)))h z|F2H&zb|q5!pr$@I2o4NJM#u`G>fxdll^F=eOtNL)NR$NSKHRC+H}x+SMFP`X*?c& zY7eg#ny%1Pf4)bU<<9+SduB&>>=6CPAK^aHa!m+(%<;*`rri=dIwxddYU!i)r-o0S zXNpGTZ=Jv9V}f<}u9H{qyfDhE`8z3kN6Q<@>)jEHx__*cu)E~?=ZsikZ1kD0O4D8{ z)oHoSE)lff>>6{u&qT_vRs5yWy=n{9ORhfRh0fg;R@--fd0u>c)%rDID<b}utU3NN zscv5P&U-?2`_$e(nYPg*G^Rw-d|S`zNW&*<pI%dHp7Y$yGWm7Emd#6^^-qej@XUIt z(D@^3ZPv@gGrcd9B@VML5`447R$C?a-ABP`^_%tTs;55M$$R|%!ik4ZpRh^!>-fIg zaPFBsKO-LeU~K+pu&=lD$MG|U&yrdHv$g5}vW>YVeEX-7n5FM6zs?Y={s<GFvw;&+ zo^a1koNl-Io@h+9INQ94hPOrPtE?OAubkO;{HWx_%a?<juT7j}^!DI%pO3CyH!9VB ztXgpBUg!E}UvKy`#ZSF@^}Jxb>6X>i1!{qFCUX7yv8TX|A=dr8OpO(X@Jf|1NA;^8 zW73+=JcBNkNjUuiyi|tu&Wpo|PafQj+yA*K?)Z)!iqMrZ8jA~YEtHAqf-RJh^x0)2 zX0kz9fCaQrM(^0>ojJw@Vs_dEQpfofZTZ@Nh%mlPJZOLC(ZnOa!c!&xiI}wd|94qE zKYXcp(;7|C4nCIa`_(cM{(jC~_y1=2aqhWDU7x43q?xz%=BF&#?RT8_k7V=4L#j!< z!h7f3Ik|`9h{d_MUmv5h&DXD;z9ENkn``2#BWq?bvT$W{v2Z^Ne!;R~N&kX#_o6x) z>SLJ{xj0td)>L{JeMI!t_Q>_7)lV#@CCpfp<|U<Vz3j-WZL2pf(~(vVmO3exFDG>8 zL86O!>6?e=r~kXMzdogQx@&F2{xdSlF|2%6OF8CTh-aN<{3U&j#h#L73%7IGTWxL? zX834Yu!~*GW%=2=FRa!6CjMWy;ZNVu(i{8UF=U_0Kge<SQ@LdB&)C$rKdRWOORt>e z<hynIW{O*zhtdrvW@pvXs=%M~PyG-1w>;eUr@X=SV^8ZH1uI%l{ZCi;&up?6Jj2wu zitR<dio@f0_OE6f&ArZh7(bh<>`jS1!&cd5)!cKhW<%kvn9}DTzaBJCi`zFta&}eT zsa-#2PqCRURJ8u^_J4OGqdUKSUVVG(>6KXpv$8T%ig&H=jSz4@`Zh~_Qq;lC1x(wd zPal7#%(`5qFyL)fe^9YAQ*}Xxb5V79f_+n4<BxqNabX4Vw`5mdI`JsAGn6GVG4-<K z#<nLX9+>-HFFp8#*YT~|X47{`R^f@vGvs1ENgq&pTwB51!M5isuY#PU(lPPW;~CfE z1il^BEOC;U?jyBaVA)oIUBTNE*HoUdI9*iL@aZs9j`9y4uQ^hme@`vs&$IZPw?95H zto`V%dG{~GEIxFrn?>-e=fgtPjf<i-t<bW4^LEXSDCT+Dbs;smZp)te>Yo1<lXBor zb^IL5zIoUFp5>T!Z%?$%rO>^a;*}F$T*_8?62i*CD{-CsP->db=@~33FYYyTc09VW zyFOylBKF(}wVj$JI~FbLZqnVXwtmN&Hyupb9E(nz+NC79YGLLs#XLcl&MACieu>)y zggsafX3YF@O)l%FOWUrdxzDRs+!mJ3=HFhYbU5~OBQI~&?7r-;ZgbDf^wSI1xG}5t zQZDnsOyysP=l?k~;lmOS73u5WcWe6HH|<>zoqg|B<(nnD0*ZdEW)H~jJUMwrW#>7Y zlPjWiPs*sI#Vs@THwp>vRubTh^U<{1%CS&<>;DDc<Wt|+mpD#!V*+z-{CnK}ye9Y7 zKWBl;P|*c{+qFJyQt{&2_CH|7U-#~B@&U^CG}E}7a*V}}-7&j%Ok#cS(vNBkkC-H# zC)zXL;JvWlg6m|1=cH9BXWSlWUtC`wWqI&%_VKR{k8R~^J{_B_H&>xneG|Lm_rk#S z%GY-@^7S*lp4onyfy4B4!GS&edu9sS{A>R#VcWmzQ18h<jr(Gn-e2?GJ&!R^=a+1F z&pVzO<tL8a;^(@tBWKpS9H|{C<sYnlq6?l{J~IlxUywC>_VI$3XNq_eKi!>noz1Y| z$9JhC3wm8lj-9Enz0-L*oprjq&g8?hf|^WjOtCm<QJt1LW82HVlHO90SoTdjk~XwG z`Lt$P$FB?(Yc_q3ozwU|H;T;($+lEW37ROv^XwO6$7{b5gSNm4ul&v428i!|HEY`3 zI@LKkVb88?J|^Ehb@ER6sD$K%C-!c33m*OuW877@PqyY;>ErV<dtA!)Wmqp1t>C!- zn44pw^LydXU3WbmiZpFYQol1d{>j45155HvwCB_mHVO2!C+D9D{KmAU{Hae-;{L** zx9g|f`&0MnW@V4!(T97=K1OgYQYo%JeWP{N+U?&GbF{C7`2-)={Kdt|mZJUm_U=v6 zNe*9R-q+bVa^5&q&li<fyYACNCSw+p1KT;v9aeiVI80%=mnwUj<wpRk<QgUS6xHBx zR>v}yN|pEtw|*-B=o6lIMR{pphewg}%j4f-*Rt<ARoGm`J|q2tYUDdM(eIt%6Vz5+ zu$YqZxck!bu2%5{GNRskezR7^Ot8Em{CVSwz5FY871r!4^!lN)_m%3w0F{#=Hz(%q zUZZnUD?4HpquBghja_LocP$f&E%&tP+N@$R&v%N1MDTfzlam{Dc$M!w`_nV?@4wjk z?Iw+fL+&m6G+l@_Z(_>Q$fg2?-<jS!vNH^)dNo8P<Z)l0JzE*a6qLk<YlgY8#UcB2 zwCr3j)oSK&Ja6g^y?ODb%Zd5%wLAViz1m(SVEN@^?Ek#vX8x^akJtQTWAvEzcA^3U z!^u4hm?z$25jh%Wa?OzCo`CG+?OU9b{@x0>Y#jIh%%6)htQrq;FsT;=f#;yoH^|)9 z`J#HoqF2~g<keKo51X`_Pll&Nr=&&;N6M}dD0}juFYEN96H~r;omp4%dD}XVdotw* zA9TcQZ4Lr&x9vQ#uP)_s_pwIFWZsy)NHbAqZ27~FuZvwJuPJ!&bHx0PUrVK|6lAOx zNcE*O*J(DWM_u9&5WKl1_V|X-l|S^Zd^>dXN<~lD_pi4P$=4Y!TU``?W8c<Umc=p& z((F(8;`!RqCZjG)&A9C*JTG+1tKesON4Ea&TeI}Bz2*6ThAp{DPYT+0g)4@|_==m_ ztXdL#<yuws8Y@H9$ZH3!t}vvtm6WM$-1YF&8;{8<2bQ?E<w%ITD$R^>VEw$%+<eBg z*ayOodL(5%8`KV5Jeu?R0Q>)j<<gJ4XRnT5uV>$MR_gP!!@KX#xT&1<<_vfui1pdq zc|UCr$BSrYeM)HIf6N`rrsKnWg>Qpp=yO@u4WW_3UnW{fb#7AA)Uy{d`JB-5cT)8u z=f%NpmJ@d0*MGPtqD)lydrnS9qWqUD2efyG{%>SzzO&=B*vyCPp8GYl?<=iunshk+ z=7POjAFh8ECt%)e65j07%V4j4=%m+2gQh#HS?((x+IZsAs<6JVT}A7Qs$Olqrft}z zpk{UTLfTS>XeYyv;PqG9{%xE0E~~#R>HEyZ>CTsVuNOa9_HNx8^QxU1Hw*sqbtf#h zy<d7`$us9f<z4X=4<`t0j4Eog<>KntaZ5&Cq_i>ce6KlEXN{b~#Pc#Lre!>9kFT{< z3Xr;8Z6mqhO3~cBtZL_w^zew(@VI36s!69`y*{z>wbX@cf}z(`ch6-yylLz6la?E; z--txC>KuKwd#y}gibtT`Rm~TU9Vdd?8CtHVs6RhaSv-&HtgB_Gxo`EY62A2v?aDtp zpPw)LE2+OtsQXM+uKLGmDp7|xCTKFfI=w2BWy@O~KL%FaU%mE{B3Hy+ZudVdR?<<l zzL|SQJGgk$>Nb{5OwTpnSkL=<)9cX<k+%j1nqP1C@t5fMYt|p(@kaNR%%U%+=XEQ6 z-tZzo<S(DU%VSyRS9vdc53?C-7Rt?DS^KxagITOD;?}Fg?Au!c`!5u|IU}-jrAt_M zH1}KQ)Y^FAJrm4hrdQwCy}Dy@(#P!D1`hvQ?_N!RuB89!<J)D^OZn%{QMJ1!qvWa* z%T{C^_K#uX9nss-(~Pp#6u3^CJR|M<`(LHs9%s(GQ!~TP%YU_mMd+QpD+`yM{JwT_ zV9}S&tcN^%lH}%xnE5D6tM~n0ne??_S|pcdAXjCRNYEmYNkJZ7ik<-{xTOB-v`*1% zwQ=Oq4CeCGR9QMfMI)tEcs)<6$VwiN+9gIROD9Zm5?VOH(oxxavS+Kf=1dz)qm?11 zJC~+Rn&j!FwmHSfz95g)%aip~@RBJZ3zkfo6y!B&$|kAW9NQMAr4w75-7hT8^-|XC zRdG^YJu_iBXKJ+CjVU49Dw-y5G_mjVRLSf<ag9fb^S1M`mI*Aa7Rx+SA77iID-k57 zv@%pymSJT<hqcw4May<<dR+0?`03t+*ByBiZ%mWAr)Kl@^slGy=ly=ho8_PJsXur5 zEd#Ap3d-$ELJS<vD0x|_yLgHO`nrgmQu4A>cR48%=-VQHO2NxUT}m}bs#GE{l$Yt! zhOB!E4_XpR-xPma&bV5NeMMx7=kpdFuMJ$vtEJ}MvMjJ#S!;jym#OF)ecm<OM82F) z<ezb|dOL$alEKPVB{A*{u9b}*>d8O(CjZ)-(!zMTS6t(Vu&e$r!-Pf49~}#pIQ_!i z>~z~(H_d&4Y88CT%;&T8v4&OLXg;ndW0S<W@O;(&ijKau4>Lt}uDB!fV^Q#8=2{Ke zw^C=*tUr2q9^Kov+;VS9m#jpK!ke3US{#n``ehI8_5Ms-^rLg(k5nU#<qR30ZX6Rd z&6&<E-_tr-LF)hAJCichO^#<OOgORdkmkj!k7Z?Znmnw61w2JuSU&N)C`>vp;$p-q z*!YJ<u;Ys{>qI}tkk38}-6~IgDrY%WMwO=KiaEXg$v#J}N6LHQCziwz<3N=|lb)`B z=6xxvd!kPEq%e+D{=UTd9A^@O6K3ste|P_;=>-wH^clY}EeZJH=%(M+zB@GakYLf_ zr43j2NIhs_xH3=f0f&W^=v;>$?Uylys(~@43)MObRp)E3OX*szX2Nc`?o08}seXl5 zXBaUyds~L5tq4fF(Nf2_c$KW~;ZCL1k*0?)yM`rBbv|A^lhe!0WTwGm!(zjkXL$1M vX2v|w4=c{+bf3~(Uj6qRch$x2xG#&u_r7q|hcQpZ|Cg_}xaY#4z`+0jkfDEx literal 46110 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 -- GitLab From 54f9a287e499874578d92dd0ee29058f04a1ac85 Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Sun, 2 Mar 2025 17:21:47 +0100 Subject: [PATCH 10/11] Fixed test Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- .../endpoints/TableEndpointUnitTest.java | 46 ++++++++----------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java index 092b8c563d..dca9c68595 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java @@ -525,8 +525,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void findById_publicDatabasePrivateDataPrivateSchemaAnonymous_succeeds() throws UserNotFoundException, - TableNotFoundException, NotAllowedException, DataServiceException, DatabaseNotFoundException, - AccessNotFoundException, QueueNotFoundException, DataServiceConnectionException { + TableNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { /* test */ final ResponseEntity<TableDto> response = generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, null, null, null); @@ -537,9 +536,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void findById_publicDataPublicSchemaAnonymous_succeeds() throws DataServiceException, - DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, - QueueNotFoundException, UserNotFoundException, NotAllowedException { + public void findById_publicDataPublicSchemaAnonymous_succeeds() throws UserNotFoundException, + TableNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { /* test */ generic_findById(DATABASE_4_ID, DATABASE_4, TABLE_9_ID, TABLE_9, null, null, null); @@ -567,9 +565,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") - public void findById_publicHasRole_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, - UserNotFoundException, NotAllowedException { + public void findById_publicHasRole_succeeds() throws UserNotFoundException, + TableNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { /* test */ final ResponseEntity<TableDto> response = generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); @@ -580,9 +577,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) - public void findById_publicNoRole_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, - UserNotFoundException, NotAllowedException { + public void findById_publicNoRole_succeeds() throws UserNotFoundException, + TableNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { /* test */ generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, USER_1_PRINCIPAL, USER_1, null); @@ -633,7 +629,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - analyseTableColumn_generic(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), null); + analyseTableColumn_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), null); }); } @@ -643,7 +639,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - analyseTableColumn_generic(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_4_PRINCIPAL); + analyseTableColumn_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_4_PRINCIPAL); }); } @@ -653,7 +649,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { DatabaseNotFoundException { /* test */ - analyseTableColumn_generic(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_1_PRINCIPAL); + analyseTableColumn_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_1_PRINCIPAL); } @Test @@ -935,8 +931,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void findById_privateDatabasePrivateDataPublicSchemaAnonymous_fails() throws UserNotFoundException, - TableNotFoundException, NotAllowedException, DataServiceException, DatabaseNotFoundException, - AccessNotFoundException, QueueNotFoundException, DataServiceConnectionException { + TableNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { /* test */ generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_2_ID, TABLE_2, null, null, null); @@ -954,9 +949,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) - public void findById_publicSchemaNotOwnerNoAccess_succeeds() throws UserNotFoundException, TableNotFoundException, - NotAllowedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, - QueueNotFoundException, DataServiceConnectionException { + public void findById_publicSchemaNotOwnerNoAccess_succeeds() throws UserNotFoundException, + TableNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { /* test */ final ResponseEntity<TableDto> response = generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_2_ID, TABLE_2, USER_4_PRINCIPAL, USER_4, null); @@ -987,9 +981,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") - public void findById_privateHasRole_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, - UserNotFoundException, NotAllowedException { + public void findById_privateHasRole_succeeds() throws UserNotFoundException, + TableNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { /* test */ final ResponseEntity<TableDto> response = generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); @@ -1001,8 +994,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) public void findById_privateDatabasePrivateDataPrivateSchemaNoRole_succeeds() throws UserNotFoundException, - TableNotFoundException, NotAllowedException, DataServiceException, DatabaseNotFoundException, - AccessNotFoundException, QueueNotFoundException, DataServiceConnectionException { + TableNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { /* test */ generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_4_PRINCIPAL, USER_4, DATABASE_1_USER_4_READ_ACCESS); @@ -1149,9 +1141,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { assertNotNull(body); } - public void analyseTableColumn_generic(UUID databaseId, Database database, UUID tableId, UUID columnId, - TableColumn tableColumn, Principal principal) - throws MalformedException, TableNotFoundException, DatabaseNotFoundException { + public void analyseTableColumn_generic(UUID databaseId, UUID tableId, UUID columnId, TableColumn tableColumn, + Principal principal) throws MalformedException, TableNotFoundException, + DatabaseNotFoundException { /* mock */ when(entityService.suggestByColumn(tableColumn)) -- GitLab From 940964f89bd73262854167c1608d65cf03e0c537 Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Sun, 2 Mar 2025 17:35:32 +0100 Subject: [PATCH 11/11] Removed non-testable tests Signed-off-by: Martin Weise <martin.weise@tuwien.ac.at> --- .../endpoints/TableEndpointUnitTest.java | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java index dca9c68595..fa1339d30a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java @@ -522,18 +522,6 @@ public class TableEndpointUnitTest extends AbstractUnitTest { generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); } - @Test - @WithAnonymousUser - public void findById_publicDatabasePrivateDataPrivateSchemaAnonymous_succeeds() throws UserNotFoundException, - TableNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { - - /* test */ - final ResponseEntity<TableDto> response = generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, null, null, null); - final TableDto body = response.getBody(); - assertNull(body.getConstraints()); - assertEquals(List.of(), body.getColumns()); - } - @Test @WithAnonymousUser public void findById_publicDataPublicSchemaAnonymous_succeeds() throws UserNotFoundException, @@ -937,16 +925,6 @@ public class TableEndpointUnitTest extends AbstractUnitTest { generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_2_ID, TABLE_2, null, null, null); } - @Test - @WithMockUser(username = USER_4_USERNAME) - public void findById_privateSchemaNotOwnerNoAccess_fails() { - - /* test */ - assertThrows(NotAllowedException.class, () -> { - generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, USER_4_PRINCIPAL, USER_4, null); - }); - } - @Test @WithMockUser(username = USER_4_USERNAME) public void findById_publicSchemaNotOwnerNoAccess_succeeds() throws UserNotFoundException, -- GitLab